Files
fd62842391 feat: add read-only orders & conversions support (#657)
* feat(orders,conversions): add read-only orders & conversions support

Extract read-only orders and conversions capabilities from the
exchange-connectivity feature branch. This includes GET API endpoints,
sync workflows from exchanges, and storage layer — without any
write operations (create, cancel, update status).

Scope:
- Models: Order, Conversion types with enums and IDs
- Migration: tables orders, order_adjustments, conversions
- Storage: Upsert, Get, List, DeleteFromConnectorID
- API: GET /orders, GET /orders/{id}, GET /conversions, GET /conversions/{id}
- Workflows: FetchNextOrders, FetchNextConversions, FetchExchangeData
- Activities: PluginFetchNextOrders/Conversions, StorageOrdersUpsert/Get, StorageConversionsUpsert
- Plugin: coinbaseprime fetch orders/conversions support
- OpenAPI: schemas and GET endpoints for orders/conversions

* fix(orders,conversions): address review findings from code review

- Add TASK_FETCH_ORDERS/CONVERSIONS cases in runNextTasksV3_1 (was blocking connector install)
- Format assets with currency.FormatAsset (BTC -> BTC/8) to pass validation
- Fix BUY/SELL source/target asset semantics
- Add Raw to OrderAdjustment/Conversion MarshalJSON/UnmarshalJSON
- Add Adjustments to OrderExpanded.MarshalJSON
- Protect enum Value() against writing UNKNOWN to DB
- Add missing index on order_adjustments(order_id)
- Fix createdAt idempotency (error instead of time.Now fallback)
- Fix PARTIALLY_FILLED detection with numeric comparison
- Propagate conversion errors instead of silently skipping
- Qualify columns in conversionsQueryContext
- Remove dead code StorageOrdersGet activity
- Remove empty CAPABILITY_FETCH_CONVERSIONS from coinbaseprime
- Remove unnecessary transaction in ConversionsUpsert
- Fix walletId -> walletID for naming consistency
- Fix %v -> %w in workflow error wrapping
- Add raw field to V3OrderAdjustment OpenAPI schema

* feat: generated

* feat(coinbaseprime): network-scoped symbols, thread-safe currencies & gross amount docs

Add network-scoped symbol resolution (e.g. BASEUSDC → USDC) to handle
Coinbase Prime assets that expose network aliases. Introduce thread-safe
lazy loading of currencies via sync.Mutex with double-checked locking
pattern (ensureCurrencies). Document gross amount convention across
models and connector template.

* feat: pre-commit

* test(coinbaseprime): add unit tests for orders fetching

Cover all order conversion paths: BUY/SELL direction, status mapping
(including PARTIALLY_FILLED detection), order types, time-in-force
variants, error cases, pagination, and edge cases for empty fields.

* feat(workbench): add orders & conversions support with Exchange plugin type

Integrate Orders and Conversions into the workbench tool so connectors
declaring TASK_FETCH_ORDERS or TASK_FETCH_CONVERSIONS are fully exercised
during local development.

Backend: task recognition, response types, in-memory storage, engine
fetch loops, HTTP endpoints, and baseline capture.

Frontend: Order/Conversion types and API methods, dedicated tabs with
table views and detail panels, dashboard buttons and stat cards.

Also adds PluginTypeExchange enum value and reclassifies CoinbasePrime
from PSP to Exchange with distinct UI badge styling.

* feat(coinbaseprime): implement conversions support and update capabilities

- Replace capability for fetching exchange data with fetching conversions in the Coinbase Prime plugin.
- Introduce new functionality to fetch conversions, including error handling and state management.
- Add comprehensive unit tests for conversions, covering various scenarios and edge cases.
- Update the plugin to handle wallet mappings and ensure thread safety for currency operations.
- Enhance event handling for order-related activities, including sending events for order adjustments.

* fix: address CodeRabbit review findings

- Fix data race in ensureCurrencies (always take lock before reading)
- Fix JSON round-trip on UNKNOWN enums (accept "UNKNOWN" in FromString)
- Add missing sort_id to conversion storage struct
- Remove IF NOT EXISTS from versioned migration SQL
- Use direct enum comparison in Value() methods

Made-with: Cursor

* feat(conversions): add EventsSendConversion activity and event handling

- Introduced EventsSendConversion activity to publish conversion events.
- Updated workflow to send conversion events when the event outbox pattern is disabled.
- Enhanced event message structure for conversions, including new fields and JSON marshaling.
- Added event type for saved conversions in the events package.

This update improves the handling of conversion events, ensuring they are properly published and managed within the workflow.

* feat(api): enhance OpenAPI schema with new connector type and conversion fields

- Added `connectorType` field to the V3Connector schema, referencing the new V3ConnectorTypeEnum.
- Updated conversion-related schemas to replace `targetAsset` with `destinationAsset` and added new fields: `quoteAmount`, `quoteAsset`, `priceAsset`, `sourceAccountID`, and `destinationAccountID`.
- Introduced V3ConnectorTypeEnum with enumerated values: PSP, OPEN_BANKING, BOTH, and EXCHANGE.
- Updated documentation to reflect changes in API responses and models.

This update improves the clarity and functionality of the API, ensuring better integration and usage of connector types and conversion details.

* Update connector capabilities JSON to reflect new and modified connectors

- Replaced the "coinbaseprime" capability for fetching exchange data with fetching conversions.
- Added "bankingbridge" connector with its associated capabilities.
- Updated "coinbaseprime" to include fetching conversions and removed fetching exchange data.
- Ensured consistency in connector capabilities across the document.

This change enhances the accuracy of connector capabilities and supports the latest integration requirements.

* fix: ensure connectors are enriched only when cursor is not nil

- Added a nil check for the cursor before enriching connectors with type.
- This change prevents potential nil pointer dereference errors and improves the robustness of the ConnectorsList function.

* test: add unit tests for conversion and order message payloads

- Introduced comprehensive tests for `ConversionMessagePayload` and `OrderMessagePayload` to validate JSON marshaling and unmarshaling.
- Added scenarios to check handling of all fields, including optional and nil values, ensuring robust serialization and deserialization.
- Implemented round-trip tests to confirm data integrity during JSON conversion.
- Enhanced coverage for conversion statuses and order directions with dedicated tests for their string representations and JSON handling.

This update improves the reliability of message payloads and ensures adherence to expected behaviors in various scenarios.

* refactor: remove deprecated order and conversion event handling

- Deleted the EventsSendOrder and EventsSendConversion activities as they are no longer used in the workflow.
- Updated the workflow to handle order and conversion events using a new outbox pattern, improving event management.
- Enhanced the fetchOrders and fetchConversions functions to marshal event payloads and insert them into the outbox.
- Added unit tests for new event structures to ensure proper functionality and data integrity.

This update streamlines event handling and prepares the codebase for future enhancements.

* feat(connectors): add connectorType field and enhance JSON handling

- Introduced `connectorType` field in the ConnectorBase and Connector structs to support new connector types.
- Updated JSON marshaling and unmarshaling methods to include the new field, ensuring proper serialization.
- Enhanced the PluginTypeFromString function to map string values to the new PluginType enum.
- Modified BaselineDiff and BaselineManager to include order and conversion comparisons, improving data integrity checks.

This update enhances the connector model and improves the handling of orders and conversions in the workbench tool.

* fix(coinbaseprime): Enhance transaction handling

- Modified transaction handling in the Coinbase Prime plugin to improve conversion processing and metadata management.
- Refactored transaction and order methods to utilize the new currency library for precision handling.
- Enhanced metadata handling by introducing a prefix for Coinbase-specific fields, ensuring consistency across transaction types.

This update improves the development environment and enhances the robustness of transaction processing in the Coinbase Prime plugin.

* refactor(connectors): remove connectorType field and related references

- Eliminated the `connectorType` field from the ConnectorBase and Connector structs, simplifying the connector model.
- Updated JSON marshaling and unmarshaling methods to reflect the removal of the `connectorType` field.
- Removed the V3ConnectorTypeEnum and its associated documentation, as it is no longer needed.
- Adjusted the ConnectorsList service to enhance error handling and streamline connector processing.

This update cleans up the connector model and improves the overall codebase by removing unnecessary complexity.

* fix: migration ordering

* fix: wrong usage of outbox event and ensure we create adjustments on important changes

* fix: pre-existing test failures

* fix: make conversion use transactions for outbox events

* fix: improve comment on ClientOrderID field

* fix: added a bunch of missing tests

* fix: nitpicks on indentation & openAPI field names

* fix: review assets & wallet loading. IMHO a controversial commit, I don't like it much

* feat: added account_lookup capability for plugins

* feat: added boostraping workflows

* feat: add boostraping to the install workflow

* feat: enable the new feature to ensure Coinbase loads wallets correctly

* refactor: merge 2 migrations

* fix: move non dependant tasks non children of fetch accounts

* fix: avoid refetching everything all the time; also introduce walletType as it's a mandatory parameter for fetchAccounts

* fix: ensure we start sub tasks as required

* doc: quick improvement on docs

* fix: rename field to be consistent with api

* fix: reset source adn dest account ids on conversions & orders during unmarshalling

* fix: render a valid PSPOrder when calling toPSPOrder

* fix: remove the misleading idempotency key on order model

* fix: use the new feature to generate account id from ID & ref even in payments

* feat: enable health monitoring for the new capabilities

* fix: ensure wallets/currency map is getting only one account

* doc: mention the new interface capabilities for plugins

* doc: improve openapi doc

* doc: add to contributing.md

* fix: make it clear only fetchNExtAccount is available in bootstrap right now

* fix: make sure we tests all capabilities in the healthcheck test

* fix: generate sdk

* feat: use schedule for surfacing bootstraping/install issues in the UI

* fix: ensure we're loading the currencies at the right time

* fix: simplify claude.md

* doc: improve openapi docs

* fix: regenerate pkg

* fix: update .codecov setting to ignore all generated files

* test: added extra coverage of base models

---------

Co-authored-by: thierrycoopman <[email protected]>
Co-authored-by: fabrice guery <[email protected]>
2026-04-23 06:37:36 +00:00

13 KiB
Raw Permalink Blame History

V3Conversion

A currency or asset conversion executed on a PSP (e.g. Coinbase Prime transfer between a USD and USDC wallet). Conversions are read-only in the Formance API: they are fetched from the underlying connector. Unlike orders, conversions do not carry an adjustment history — Formance records the final state only.

Fields

Field Type Required Description
ID string ✔️ Formance-assigned unique conversion ID.
ConnectorID string ✔️ ID of the Formance connector this conversion was fetched from.
Provider string ✔️ Provider name of the connector (e.g. coinbaseprime).
Reference string ✔️ PSP-assigned conversion reference. Unique within the connector.
CreatedAt time.Time ✔️ When the conversion was initiated on the PSP.
UpdatedAt time.Time ✔️ When Formance last observed a state change on the conversion.
SourceAsset string ✔️ Asset being converted from, in SYMBOL/precision form (e.g. USD/2).
DestinationAsset string ✔️ Asset being converted to, in SYMBOL/precision form (e.g. USDC/6).
SourceAmount *big.Int ✔️ Amount of source asset debited, as an integer at sourceAsset precision.
DestinationAmount *big.Int ➖ Amount of destination asset credited, at destinationAsset precision. Null until the conversion completes.
Fee *big.Int ➖ PSP fee for the conversion, at feeAsset precision.
FeeAsset *string ➖ Currency the fee is denominated in, in SYMBOL/precision form.
Status components.V3ConversionStatusEnum ✔️ Lifecycle of a conversion.
PENDING — accepted by the PSP, not yet settled.
COMPLETED — settled, terminal.
FAILED — rejected or reverted, terminal. See error.
SourceAccountID *string ➖ Formance account ID of the wallet the source asset was debited from.
DestinationAccountID *string ➖ Formance account ID of the wallet the destination asset was credited to.
Metadata map[string]string ➖ N/A
Error *string ➖ Human-readable error from the PSP when status is FAILED. Null otherwise.