Project

squake

0.01
The project is in a healthy, maintained state
This gem provides an interface for the SQUAKE API to calculate and compensate carbon emissions.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

Runtime

 Project Readme

SQUAKE

Find the documentation here: docs.

This gem follows SemVer, however only after a stable release 1.0.0 is made.

Installation

Via rubygems:

gem 'squake'

Test the latest version via git:

gem 'squake', git: 'git@github.com:squake-earth/squake-ruby', branch: :main

Auth

An API Key can be generated on the dashboard You need a different API Key for production and sandbox.

Functionality

  • compute emission values
  • request a price quote for your emissions (with a product id)
  • place a purchase order (with a price quote id)
  • get a list of all available products (includes price information)

Usage

Initialize the client

either explicitly anywhere in the app

config = Squake::Config.new(
  api_key: 'Your API Key',     # required
  sandbox_mode: true,          # optional, default: true
  keep_alive_timeout: 30,      # optional, default: 30
  logger: Logger.new($stdout), # optional, default: Logger.new($stdout)
  enforced_api_base: nil,      # optional, default: nil. If given, overrides the API base URL.
)

# the SQUAKE client emits canonical log lines, e.g.
#   Request started http_method=get http_path=/api/v2/calculations
client = Squake::Client.new(config: config)

or once globally in e.g. an initializer

Squake.configure do |config|
  config.api_key = ENV.fetch('SQUAKE_API_KEY') # optional if ENV var `SQUAKE_API_KEY` is set
  config.sandbox_mode = true                   # set to `false` for production
  config.keep_alive_timeout = 30               # optional, default: 30
  config.logger = Logger.new($stdout)          # Set this to `Rails.logger` when using Rails
  config.enforced_api_base = nil               # for testing to e.g. point to a local server
end

If you have the API Key in an ENV var named SQUAKE_API_KEY, you don't need any further config.

Fetch available products

context = Squake::Products.get
products = context.result # [Squake::Model::Product]

Define items you want emissions to be computed

Find all available item types and methodologies in the docs.

# NOTE: some items are also available as typed objects, found at `lib/squake/model/items/**/*.rb`
#       where `.../items/private_jet/squake` is the item for type "private_jet" and methodology "squake".
items = [
  {
    type: 'flight',
    methodology: 'ICAO',
    origin: 'BER',
    destination: 'SIN',
    booking_class: 'economy',
    number_of_travellers: 2,
    aircraft_type: '350',
    external_reference: 'booking-id',
  },
  Squake::Model::Items::PrivateJet::Squake.new(
    origin: 'SIN',
    destination: 'HND',
    external_reference: 'my-booking-id',
    identifier: 'P180',
    identifier_kind: 'ICAO',
  ),
]

Calculate emissions (without price quote)

context = Squake::Calculation.create(
  items: items,          # required
  carbon_unit: 'gram',   # optional, default: 'gram', other options: 'kilogram', 'tonne'
  expand: [],            # optional, default: [], allowed values: 'items' to enrich the response
  client: client,        # optional
)

# alias: context.failed?
if context.success?
  context.result # Squake::Model::Carbon
else
  context.errors # [Squake::Errors::APIErrorResult]
end

Get a price quote alone

For a given carbon quantity

Squake::Pricing.quote(
  client: squake_client,                           # optional
  carbon_quantity: 1000,                           # required
  carbon_unit: 'kilogram',                         # optional, default: 'gram', other options: 'kilogram', 'tonne'
  product_id: 'some_product_id',                   # required
  expand: [],                                      # optional, default: [], allowed values: 'product', 'price' to enrich the response
  payment_link_return_url: 'https://squake.earth', # optional, default: nil
)

if context.success?
  context.result # Squake::Model::Pricing
else
  context.errors # [Squake::Errors::APIErrorResult]
end

For a given fixed total

context = Squake::Pricing.quote(
  client: squake_client, # optional
  fixed_total: 1000, # required
  currency: 'USD', # optional, default: 'EUR'
  product_id: 'some_product_id', # required
  expand: [], # optional, default: [], allowed values: 'product', 'price' to enrich the response
)

if context.success?
  context.result # Squake::Model::Pricing
else
  context.errors # [Squake::Errors::APIErrorResult]
end

Calculate emissions and include a price quote

context = Squake::CalculationWithPricing.quote(
  items: items,                                    # required
  product: 'product-id',                           # required
  currency: 'EUR',                                 # optional, default: 'EUR'
  carbon_unit: 'gram',                             # optional, default: 'gram', other options: 'kilogram', 'tonne'
  expand: [],                                      # optional, default: [], allowed values: 'items', 'product', 'price' to enrich the response
  payment_link_return_url: 'https://squake.earth', # optional, default: nil
  client: client,                                  # optional
)

if context.success?
  context.result # Squake::Model::Pricing
else
  context.errors # [Squake::Errors::APIErrorResult]
end

Place a purchase order

by default the library injects a SecureRandom.uuid as external_reference to ensure idempotency, i.e. you can safely retry the request if it fails.

uuid = SecureRandom.uuid

# returns Squake::Model::Purchase
context = Squake::Purchase.create(
  pricing: pricing.id,      # required, from above
  external_reference: uuid, # optional, default: SecureRandom.uuid, used for idempotency, if given, MUST be unique
  client: client,           # optional
)

context.result # Squake::Model::Purchase
context.errors # [Squake::Errors::APIErrorResult]

# retrieve the purchase later
Squake::Purchase.retrieve(
  id: purchase.id, # required
  client: client,  # optional
)

# within 14 days, you can cancel the purchase worry-free
Squake::Purchase.cancel(
  id: purchase.id, # required
  client: client,  # optional
)

Contributions

We welcome contributions from the community. Before starting work on a major feature, please get in touch with us either via email or by opening an issue on GitHub. "Major feature" means anything that changes user-facing features or significant changes to the codebase itself.

Please commit small and focused PRs with descriptive commit messages. If you are unsure about a PR, please open a draft PR to get early feedback. A PR must have a short description ("what"), a motiviation ("why"), and, if applicable, instructions how to test the changes, measure performance improvements, etc.

Publishing a new version

run

bin/release

which will guide you through the release process.