Mosaic SDK
Ruby SDK for the Mosaic API. Provides a simple interface to manage banks, DNAs, clones, and NAVs, routed through the Fluence API gateway.
Installation
Add the gem and its fluence-gateway-client runtime dependency to your application's Gemfile (both are hosted on GitHub Packages):
source 'https://rubygems.pkg.github.com/fluence-eu' do
gem 'mosaic-sdk'
gem 'fluence-gateway-client'
end
Then run:
bundle install
Configuration
Credentials and gateway URLs are managed by fluence-gateway-client. Set APPCENTER_CLIENT_ID and APPCENTER_CLIENT_SECRET and you're done — the SDK targets the built-in :mosaic tenant out of the box.
For overrides (URL, profile, SSL, etc.), see the fluence-gateway-client README.
Usage
Banks
# List all banks
banks = Mosaic::Sdk.Bank.list
# Search banks by name
banks = Mosaic::Sdk.Bank.list('My Bank')
# Get a specific bank
bank = Mosaic::Sdk.Bank(123).data
DNAs
# List all DNAs
dnas = Mosaic::Sdk.Dna.list
# Get a specific DNA
dna = Mosaic::Sdk.Dna(42).data
# List clones for a DNA
clones = Mosaic::Sdk.Dna(42).clones.list
# Get a specific clone for a DNA
clone = Mosaic::Sdk.Dna(42).clones(5).data
Clones
# List all clones
clones = Mosaic::Sdk.Clone.list
# Search clones by name
clones = Mosaic::Sdk.Clone.list('My Clone')
# Filter clones by code type
clones = Mosaic::Sdk.Clone.list(type: 'isin')
# Search and filter by code type
clones = Mosaic::Sdk.Clone.list('My Clone', type: 'isin')
# Get a specific clone
clone = Mosaic::Sdk.Clone(10).data
# Create a clone
clone = Mosaic::Sdk.Clone.create(
name: 'My Clone',
codes: [{ type: 'isin', value: 'FR0000000001' }],
source: 'manual',
dna_id: 42,
account_references: ['REF001']
)
# Create a clone within a DNA context (dna_id is inferred)
clone = Mosaic::Sdk.Dna(42).clones.create(
name: 'My Clone',
codes: [{ type: 'isin', value: 'FR0000000001' }],
source: 'manual'
)
# List NAVs for a clone
navs = Mosaic::Sdk.Clone(10).navs.list
NAVs
# Get the latest NAV for a clone
nav = Mosaic::Sdk.Clone(10).navs.latest.data
# Get NAV for a specific date
nav = Mosaic::Sdk.Clone(10).navs.for_date('2026-01-15').data
# Also works with Date objects
nav = Mosaic::Sdk.Clone(10).navs.for_date(Date.today).data
# Create a NAV
nav = Mosaic::Sdk.Clone(10).navs.create(
price: 150.25,
unit: 'price',
date: '2026-03-11',
pricing_method: 'net_asset_value_final',
bank_id: 1
)
Batch reads by code
Resolve many resources by external code (ISIN, …) in a single call, via list(codes:). These return a Hash keyed by the requested code whose values are Instance objects — read attributes with [] (string or symbol keys) and chain associations directly.
# Clone metadata by code (optionally a richer view)
clones = Mosaic::Sdk.Clone.list(codes: %w[FR0000000001 LU0000000002], view: :full)
clones['FR0000000001'][:name]
# Latest NAV per code (optionally with a date ceiling, optionally a richer view)
navs = Mosaic::Sdk.Nav.list(codes: %w[FR0000000001], to: Date.today, view: 'with_documents')
navs['FR0000000001'].first[:price]
# NAVs over a date range
history = Mosaic::Sdk.Nav.list(
codes: %w[FR0000000001],
from: Date.new(2026, 1, 1),
to: Date.today
)
# => { "FR0000000001" => [#<Nav::Instance>, ...] }
The top-level Mosaic::Sdk.Nav collection only supports these code-addressed reads; create NAVs under a clone (Mosaic::Sdk.Clone(10).navs.create).
Targeting a currency line
A security can have one clone per currency (a dual listing in EUR and GBX is two valuation units). A bare code entry resolves the security's unique clone — when the code is carried by several currency lines it is ambiguous and omitted from the response; target a line explicitly with a Hash carrying code: and currency:. Entries can be mixed freely, and object entries are keyed CODE|CURRENCY in the response:
Mosaic::Sdk.Clone.list(codes: ['FR0000000001', { code: 'FR0000120271', currency: 'EUR' }])
# => { "FR0000000001" => #<Clone::Instance>, "FR0000120271|EUR" => #<Clone::Instance> }
The resolved instances chain like any other:
clone = Mosaic::Sdk.Clone.list(codes: [{ code: 'FR0000120271', currency: 'EUR' }])['FR0000120271|EUR']
clone.navs.create(price: 100.0, unit: 'price', date: '2026-07-01', pricing_method: 'net_asset_value_final', bank_id: 3)
Trading venues
The trading venue (ISO 10383 MIC) is price provenance, not identity. When creating a clone, mic: records the security's default/primary listing venue (it backfills the default venue when the push resolves to an existing clone without one):
clone = Mosaic::Sdk.Clone.create(
name: 'My Clone',
codes: [{ type: 'isin', value: 'FR0000120271' }],
source: 'manual',
dna_id: 42,
mic: 'XPAR'
)
When creating a NAV, mic: records the venue the price was observed on — the same date can carry one price per venue:
clone.navs.create(price: 100.0, unit: 'price', date: '2026-07-01',
pricing_method: 'net_asset_value_final', bank_id: 3, mic: 'XPAR')
Reading back, Mosaic::Sdk.Nav.list(codes:) accepts the same mic: alongside a kind: ('price' or 'percentage') in an object entry, to filter the resolved line down to a single price series — the clone resolved is still the one matching code:/currency: only, mic:/kind: never affect which line is picked:
Mosaic::Sdk.Nav.list(codes: [{ code: 'FR0000120271', currency: 'EUR', mic: 'XPAR', kind: 'price' }])
# => { "FR0000120271|EUR|XPAR|price" => [#<Nav::Instance>, ...] }
Chaining associations
Models support association chaining from DNA down to NAV:
# DNA -> Clones -> NAVs
latest_nav = Mosaic::Sdk.Dna(42).clones(5).navs.latest.data
Development
After checking out the repo, run bin/setup to install dependencies.
Use bin/console for an interactive prompt with the SDK pre-loaded. Set the APPCENTER_CLIENT_ID and APPCENTER_CLIENT_SECRET environment variables (read directly by fluence-gateway-client) before launching:
APPCENTER_CLIENT_ID=your_id APPCENTER_CLIENT_SECRET=your_secret bin/console
Run the full catalog (lint + security + codequality + tests) with:
bundle exec fluence-ci all
License
The gem is available as open source under the terms of the MIT License.