8000 feat: Add crypto currency support with global toggle by davidpatters0n · Pull Request #401 · Shopify/money · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat: Add crypto currency support with global toggle #401

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 15, 2025

Conversation

davidpatters0n
Copy link
Contributor
@davidpatters0n davidpatters0n commented May 14, 2025

Adds support for cryptocurrencies to the Money gem, starting with USDC stablecoin. It's implemented through a clean configuration system that makes crypto handling seamless while maintaining backward compatibility.

Changes

  • Added crypto_currencies config option (defaults to false)
  • Created a dedicated crypto.yml file for cryptocurrency definitions
  • Updated Currency and Currency::Loader to properly handle crypto currencies
  • Added comprehensive test coverage for new functionality
  • Bumped version to 3.1.0 for this feature release

Breaking changes

None! The feature is opt-in and disabled by default, so existing code will continue to work without any changes.

Configuration System

Before

# No built-in crypto support
Money.new(100, "USDC") # Raises UnknownCurrency

# Would require manual currency registration
currencies = Money::Currency.currencies
currencies.merge!("USDC" => { ... }) # Hacky workaround

After

# Just enable the config option
Money.config.crypto_currencies = true
Money.new(100, "USDC") # Works!

# Or use the configuration block
Money.configure do |config|
  config.experimental_crypto_currencies = true
end

Example Usage

# In an initializer
Money.configure do |config|
  config.experimental_crypto_currencies = true
end

# Create and use crypto currency objects
usdc = Money.new(1000, "USDC")
usd = Money.new(1000, "USD")

@davidpatters0n davidpatters0n self-assigned this May 14, 2025
@davidpatters0n davidpatters0n changed the base branch from add-experimental-currency-framework to main May 14, 2025 00:34
@davidpatters0n davidpatters0n requested a review from elfassy May 14, 2025 00:34
@davidpatters0n davidpatters0n force-pushed the add-global-experimental-currency branch from 193878d to 1a371a5 Compare May 14, 2025 00:43
@davidpatters0n davidpatters0n force-pushed the add-global-experimental-currency branch 2 times, most recently from 9047b40 to c64f55d Compare May 14, 2025 16:44
Add support for cryptocurrencies with USDC as the first implementation.
This feature is opt-in and disabled by default.

- Add crypto_currencies config option (default: false)
- Add crypto.yml for cryptocurrency definitions
- Implement crypto currency lookup in Currency class
- Add load_crypto_currencies method to Currency::Loader
- Add test
- Update README with usage documentationt
disambiguate_symbol: USDC
alternate_symbols: []
subunit: Cent
subunit_to_unit: 100
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why two decimal places see; #398 (comment) for more context. In addition if there is a need to override we can do as mentioned on the same comment.

@@ -5,14 +5,20 @@
class Money
class Currency
module Loader
CURRENCY_DATA_PATH = File.expand_path("../../../../config", __FILE__)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
CURRENCY_DATA_PATH = File.expand_path("../../../../config", __FILE__)
CURRENCY_DATA_PATH = File.expand_path("../../../config", __dir__)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed 👍🏽

expect(currency.iso_code).to eq('USDC')
expect(currency.symbol).to eq('USDC')

Money.config = old_config
Copy link
Member
@antw antw May 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Does this been to be in an ensure block?

If the test fails I'm assuming the config won't be restored to the previous state and the custom config might affect other tests. I'm guessing we need something like:

old_config = Money.config

begin
  # the test
ensure
  Money.config = old_config
end

I wonder if it's worth adding a with_config method here? Edit: My suggestion isn't thread-safe, and refactoring Money.config to be thread-safe is likely not worthwhile. Maybe a test helper?

def with_config(config)
  old_config = Money.config
  Money.config = config
  yield
ensure
  Money.config = old_config
end

old_config = Money.config
Money.config = Money::Config.new.tap do |config|
config.default_currency = default_currency if default_currency
config.legacy_json_format! if legacy_json_format
config.legacy_deprecations! if legacy_deprecations
config.legacy_default_currency! if legacy_default_currency
config.crypto_currencies = true if crypto_currencies
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
config.crypto_currencies = true if crypto_currencies
config.crypto_currencies = crypto_currencies unless crypto_currencies.nil?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be a boolean and then just config.crypto_currencies = crypto_currencies?

old_config = Money.config
Money.config = Money::Config.new.tap do |config|
config.default_currency = default_currency if default_currency
config.legacy_json_format! if legacy_json_format
config.legacy_deprecations! if legacy_deprecations
config.legacy_default_currency! if legacy_default_currency
config.crypto_currencies = true if crypto_currencies
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be a boolean and then just config.crypto_currencies = crypto_currencies?

@davidpatters0n davidpatters0n requested a review from antw May 15, 2025 13:44
@davidpatters0n davidpatters0n force-pushed the add-global-experimental-currency branch from e41a0a0 to cdb107a Compare May 15, 2025 13:44
Copy link
Member
@antw antw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing all the comments. LGTM!

@davidpatters0n davidpatters0n force-pushed the add-global-experimental-currency branch 3 times, most recently from 90c56f8 to 716b09d Compare May 15, 2025 14:48
@davidpatters0n davidpatters0n merged commit 87e9a1d into main May 15, 2025
7 checks passed
@davidpatters0n davidpatters0n deleted the add-global-experimental-currency branch May 15, 2025 14:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants
0