npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, πŸ‘‹, I’m Ryan HefnerΒ  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you πŸ™

Β© 2024 – Pkg Stats / Ryan Hefner

@automatedtf/monetare

v0.0.16

Published

πŸ’± Library to represent, perform arithmetic, encode, and swap between the currency systems within TF2

Downloads

43

Readme

Monetare πŸ’± β€’ https://github.com/automatedtf/monetare/actions/workflows/main.yml/badge.svg

πŸ“– Table of Contents

πŸ‘‹ Introduction

Monetare provides a standardisation to represent, operate and manage the currency system within Team Fortress 2. The in-game trading economy relies on a set of two currencies: keys and metal, which define the pricing basis of all items. Keys are themselves tradable items that can be priced in metal, however, as there is no consistent conversion rate, this value floats over time. As such, systems require calculations to be pegged to a single currency, which this library facilitates.

ℹ️ Prerequisite Knowledge

This library provides a large number of functions to help you work with the currency system. It is recommended that you read through this section before using the library to ensure you understand how it works.

Currencies within Team Fortress 2

The Team Fortress 2 economy utilises two main currencies: the Mann Co. Supply Crate Key and metal.

Metal is the base currency provided within the game, being generated from the crafting of items. 2 weapons can be crafted to create 1 Scrap Metal. 3 Scrap Metal can be used to craft 1 Reclaimed Metal. 3 Reclaimed Metal can be used to craft 1 Refined Metal.

These each can then be used to craft other items. Given that there is an in-game drop system that continuously provides weapons to players, there is ultimately no limit to the number of metal (Scrap, Reclaimed, or Refined).

πŸ”— Details on Metal Crafting

Over time, traders within the Team Fortress 2 affixed their own currency item, the Mann Co. Supply Crate Key to price other items due to its stable conversion to real cash dollars (~$2.50 ea.). For items less than ~$2.50 ea., metal has been used to price these items.

πŸ”— Conversion Rate of Metal to Keys over time

Currency Naming Conventions and Jargon

Traders use a set of short-hand naming conventions to represent the currencies within Team Fortress 2. Below is a list of common jargon used within the community:

  • keys - Mann Co. Supply Crate Key
  • ref - Refined Metal
  • rec - Reclaimed Metal
  • scrap - Scrap Metal
  • metal - Refined Metal, Reclaimed Metal, and Scrap Metal
  • 0.33 refined - 1 Reclaimed Metal
  • 0.11 refined - 1 Scrap Metal
  • 1.55 refined - 1 Refined Metal, 1 Reclaimed Metal, and 2 Scrap Metal
Currency Pegging

This library uses the concept of currency pegging to convert between keys and metal. When representing currencies as strings, there are two internal systems used: Metal-pegged and Key-pegged.

Metal-pegged: 376;m000  - <Scrap To Key Rate>;m<Scraps>
Key-pegged: 376;k2:001 - <Scrap To Keys Rate>;k<Keys>:<Scraps>

The affixing of the Scrap To Keys Rate to the internal representation of these systems is to allow for a user to switch between the two systems at any given time. This can also be used to index the value of an item over time in any of these systems.

For example, if an item is to represented using a key-pegged value such as 100;k2:001, then currently, the item is worth 2 keys, 1 scrap or 201 scraps. If the scrap-to-key ratio rises from 100:1 to 200:1, then the item is still worth 2 keys, 1 scrap but in terms of metal-value, it is now worth 401 scraps.

Generally, items worth more than $2.50 use key-pegged values whilst items worth less than $2.50 use metal-pegging to fix their values.

πŸ”Œ General Usage

Installation

You can install the module via npm:

npm install @automatedtf/monetare

This will add the library to your project's package.json file.

Approach to Using the Library

You will find yourself using the library in parallel to your logic.

You should attempt to represent currency values by either applying consequent operations to a Key, Refined, Reclaimed, or Scrap Currency object when first deriving the value for an item, or by using parseCurrencyString to parse a cached string representation of a currency back into a Currency object.

Example: Setting the price of an item

Consider the example of a user wishing to set the price of their item listed on a website to 1 key, 5.33 refined as POSTed to the server from submitting an input form.

import { Key, Refined, Scrap } from "@automatedtf/monetare"; 

// Parse request body data
const { key, metal, itemid }: { key: string, metal: string, itemid: string } = req.body;

console.log(key); // 1
console.log(metal); // 5.33

// Get item from database
const item = await getItemFromDatabase(itemid);

// Get amounts of each currency unit
// Note: Very simple, buggy extractor function
const metalComponents = metal.split(".");
const refined = parseInt(metalComponents[0]);
const scrap = (metalComponents.length == 2) ? Math.floor(parseFloat(metalComponents[1]) / 0.11) : 0;

// Get total of currency units
const itemPrice: Currency = Key(key).add(Refined(refined)).add(Scrap(scrap));

// Set price of item
item.price = itemPrice.toString();

await saveItemToDatabase(item);
Example: Find the amount of change to provide

Consider the example of a user buying an item from a website. We need to check that the price of the item is lower than the amount that the user's credit on the website and then take the amount from the user's balance.

import { parseCurrencyString } from "@automatedtf/monetare"; 

// Assume we already have the user object from the database
const user: { balance: string; ... } = ...;
const userBalance: Currency = parseCurrencyString(user.balance);

// Assume we already have the item object from the database
const item : { price: string; ... } = ...;
const itemPrice: Currency = parseCurrencyString(item.price);

// Check that item is worth more than the user's balance
if (userBalance.isLessThan(itemPrice)) {
    return res.status(400).send("Insufficient funds");
}

// Find change
const change = itemPrice.minus(userBalance);
user.balance = change.toString();

// Save user object
await saveUserToDatabase(user);

return res.status(200).send("Success");

🧰 Methods and Functions

The Currency interface forms the main base of the library. It provides a set of methods to help you work with either currency system (Metal-pegged or Key-pegged).

interface Currency {
    
    /* Conversions */
    toString(): string;
    toHumanReadable(): string;
    
    keyPrice(): number;
    withKeyPrice(keyPrice: number): Currency;
    
    isKeyPegged(): boolean;
    isMetalPegged(): boolean;
    toKeyPegged(): KeyPeggedCurrency;
    toMetalPegged(): MetalPeggedCurrency;

    /* Operations */
    add(otherCurrency: Currency): Currency;
    minus(otherCurrency: Currency): Currency;
    multiply(times: number): Currency;

    /* Inequalities */
    isGreaterThan(otherCurrency: Currency): boolean;
    isGreaterThanOrEqualTo(otherCurrency: Currency): boolean;
    isEqualTo(otherCurrency: Currency): boolean;
    isLessThanOrEqualTo(otherCurrency: Currency): boolean;
    isLessThan(otherCurrency: Currency): boolean;

    /* Utility */
    normalise(): Currency;
}

Interface Implementations

toString

Currency.toString() returns an internal representation of the currency.

  • Metal-pegged - <Scrap To Key Rate>;m<Scraps> e.g 376;m000
  • Key-pegged - <Scrap To Keys Rate>;k<Keys>:<Scraps> e.g 376;k2:001
toHumanReadable

Currency.toHumanReadable() returns a human readable representation of the currency.

  • Metal-pegged - e.g 0.11 refined, 5.00 refined
  • Key-pegged - e.g 1 key, 0.11 refined, 0 keys, 15.11 refined
keyPrice

Currency.keyPrice() returns the price of a Key in scraps as captured in the Currency object.

  • Metal-pegged - e.g 376 from 376;m000
  • Key-pegged - e.g 376 from 376;k3:001
withKeyPrice

Currency.withKeyPrice(keyPrice: number) returns a new Currency object with the key price set to the provided value.

  • Metal-pegged - returns Metal-pegged object
  • Key-pegged - returns Key-pegged object
isKeyPegged

Currency.isKeyPegged() returns a boolean indicating whether the currency is key-pegged.

  • Metal-pegged - returns false
  • Key-pegged - returns true
isMetalPegged

Currency.isMetalPegged() returns a boolean indicating whether the currency is metal-pegged.

  • Metal-pegged - returns true
  • Key-pegged - returns false
toKeyPegged

Currency.toKeyPegged() returns a new Key-pegged Currency object.

  • Metal-pegged - converts to a Key-pegged object
  • Key-pegged - returns this
toMetalPegged

Currency.toMetalPegged() returns a new Metal-pegged Currency object.

  • Metal-pegged - returns this
  • Key-pegged - converts to a Metal-pegged object
add

Currency.add(otherCurrency: Currency) returns a new Currency object with the values of the current object and the other object added together.

minus

Currency.minus(otherCurrency: Currency) returns a new Currency object with the values of the current object and the other object subtracted from it.

multiply

Currency.multiply(times: number) returns a new Currency object with the values of the current object multiplied by the provided value.

isGreaterThan

Currency.isGreaterThan(otherCurrency: Currency) returns a boolean indicating whether the current object is greater than the other object.

It will do this by first turning each currency into the equivalent number of scraps via _metalHash() and comparing both scraps values.

isGreaterThanOrEqualTo

Currency.isGreaterThanOrEqualTo(otherCurrency: Currency) returns a boolean indicating whether the current object is greater than or equal to the other object.

It will do this by first turning each currency into the equivalent number of scraps via _metalHash() and comparing both scraps values.

isEqualTo

Currency.isEqualTo(otherCurrency: Currency) returns a boolean indicating whether the current object is equal to the other object.

It will do this by first turning each currency into the equivalent number of scraps via _metalHash() and comparing both scraps values.

isLessThanOrEqualTo

Currency.isLessThanOrEqualTo(otherCurrency: Currency) returns a boolean indicating whether the current object is less than or equal to the other object.

isLessThan

Currency.isLessThan(otherCurrency: Currency) returns a boolean indicating whether the current object is less than the other object.

It will do this by first turning each currency into the equivalent number of scraps via _metalHash() and comparing both scraps values.

normalise

Currency.normalise() returns a new Currency object with the values of the current object normalised.

A normalisation on KeyPeggedCurrency requires the key price for a Currency object to be set. It will turn the accompanying object into scraps via _metalHash() and then convert the object back into the equivalent Currency:

  • Metal-pegged - Returns self
  • Key-pegged - Using the set key price, it will return a new KeyPeggedCurrency that gets the most amount of keys available out of the scraps and saves the rest as scraps.

Utility Functions

parseCurrencyString

parseCurrencyString(currencyString: string) returns a new Currency object from the provided string.

For metal-pegged currencies, the string should be in the format <Scrap To Key Rate>;m<Scraps> e.g 376;m000 For key-pegged currencies, the string should be in either of these formats:

  • <Scrap To Keys Rate>;k<Keys>:<Scraps> e.g 376;k2:001 - 2 keys, 1 scrap
  • <Scrap To Keys Rate>;k<Keys> e.g 376;k2 - 2 keys simply

More often or not, you can obtain this necessary string as given by the toString method.

parseMetalDecimal

parseMetalDecimal(metalDecimal: string) returns a new Currency object from the provided decimal string that represents the metal. For example, the decimal string 0.11 would be converted to a Currency object of the same value as a Scrap.

This is a helper function for applications which may take in decimal strings from user inputs.

Zero

Zero is a Key-pegged object representing zero value.

Key

Key creates a new Key-pegged Currency object that represents 1 key.

Refined

Refined creates a new Metal-pegged Currency object that represents 1 refined.

Reclaimed

Reclaimed creates a new Metal-pegged Currency object that represents 1 reclaimed or 0.33 refined.

Scrap

Scrap creates a new Metal-pegged Currency object that represents 1 scrap or 0.11 refined.

πŸ“š Helpful Resources