Set up default currency accounts automatically (#72)
This commit is contained in:
1 parent
62df9eac5f
commit
5c255296d3
21 files changed
+675
-62
No files matched your search
@@ -130,8 +130,10 @@ This recovery retains the configured provider URL, account and replay namespace.
|
||||
layout and least-privilege identities, Mongo transactions/lease rotation, and
|
||||
authenticated Sendico currency and ledger reads through the same loopback
|
||||
connection and token used by BFF. It sends no email and executes no payment.
|
||||
An empty wallet is expected until dedicated subject-bound currency ledgers and
|
||||
saved methods are provisioned as described in [payment provisioning](payments.md).
|
||||
Signup and wallet access automatically ensure subject-bound RUB, USDT and USDC
|
||||
ledgers as described in [account setup](payments.md#automatic-currency-accounts-72).
|
||||
Deploy the provider prerequisite and grant ledger-create permission first.
|
||||
Saved funding and payout methods remain separate from currency-account setup.
|
||||
|
||||
## Recovery
|
||||
|
||||
|
||||
+36
-7
@@ -52,22 +52,50 @@ coordinated deployment of the platform's financial services.
|
||||
|
||||
Reuse `api.sendico` and its existing Vault-rendered token file. Do not put provider
|
||||
credentials or organization/source settings in Flutter. Provision the integration
|
||||
account's organization membership, payment-create/read, ledger-account/balance
|
||||
read and the permissions needed to resolve its stored payment methods. Verify
|
||||
account's organization membership, payment-create/read, ledger-account create/read,
|
||||
balance read and the permissions needed to resolve its stored payment methods. Verify
|
||||
those permissions in the intended environment before enabling real operations.
|
||||
|
||||
Through Sendico's existing operator APIs, provision one dedicated unowned
|
||||
organization ledger per customer currency, with active `asset` / `operating`
|
||||
semantics, no negative balance and metadata:
|
||||
### Automatic currency accounts (#72)
|
||||
|
||||
The backend ensures **RUB, USDT and USDC** accounts after confirmed identity intake
|
||||
during signup, before sending the activation email. Resending activation retries
|
||||
the same setup. Every authenticated wallet load also ensures the defaults, so
|
||||
existing customers receive missing accounts automatically when they next open
|
||||
their wallet. This is lazy backfill, not an eager scan of dormant customers.
|
||||
|
||||
Setup creates dedicated unowned organization ledgers through the public
|
||||
`POST /ledger_accounts/{organization}` API, with active `asset` / `operating`
|
||||
semantics, zero initial funds, no negative balance and metadata:
|
||||
|
||||
| Ledger metadata | Meaning |
|
||||
| --- | --- |
|
||||
| `sxchnge_subject_ref` | Confirmed independent subject reference from sign-up |
|
||||
| `external_subject_ref` | Same confirmed subject; provider-enforced organization/subject/currency uniqueness |
|
||||
| `sxchnge_payout_method_ref` | Optional prevalidated same-currency saved payout method |
|
||||
| `sxchnge_payout_label` | Safe customer-visible destination label, e.g. bank plus masked suffix |
|
||||
| `sxchnge_funding_method_ref` | Optional same-currency saved funding source supported by the platform route |
|
||||
|
||||
These are financial-resource bindings maintained by trusted provisioning, not
|
||||
Existing customer ledgers and their balances are preserved, including manually
|
||||
provisioned ledgers with the original `sxchnge_subject_ref` tag. Only missing
|
||||
defaults are created; existing additional currencies remain visible. Repeated
|
||||
bound creates reuse the ledger and resume Sendico's durable wallet/route setup
|
||||
after an interrupted response. Frozen, duplicate or incorrectly owned bindings
|
||||
fail instead of creating a replacement. All required currency precision entries
|
||||
are checked against the provider catalog before issuing creates. Saved funding
|
||||
and payout bindings remain separate from creation of the currency accounts.
|
||||
|
||||
Deploy [Sendico #2968](https://git.sendico.io/tech/sendico/issues/2968) first:
|
||||
Ledger (including its unique index), then Product Edge, then SXCHNGE backend and
|
||||
frontend from [task #72](https://git.sendico.io/tech/sxchnge/issues/72). The public
|
||||
ledger list must advertise `externalSubjectAccounts: true` before SXCHNGE sends
|
||||
any create requests. Older providers fail safely without creating accounts.
|
||||
The acknowledgement assumes Ledger and Edge are deployed in that order; it
|
||||
does not discover the version of a separately running Ledger. No new runtime
|
||||
configuration or credentials are introduced. Existing deployments must give the
|
||||
integration principal the ledger-create permission in addition to its reads.
|
||||
|
||||
These are financial-resource bindings maintained by server-side setup, not
|
||||
client choices or new runtime configuration. Do not tag a pooled/integration-login
|
||||
ledger as a customer ledger. Do not place full bank/card details or secret values
|
||||
in labels or metadata. The BFF checks subject, organization, account type, role,
|
||||
@@ -79,7 +107,8 @@ review action. Funding uses a quote for the provisioned stored source; it does
|
||||
not mint money or treat demo top-ups as real deposits. Additional destinations,
|
||||
recipient onboarding and other funding instructions remain separate features.
|
||||
|
||||
An empty set of provisioned ledgers is an empty wallet. Existing organization
|
||||
If setup reports a failure, the API returns an unavailable wallet rather than an
|
||||
empty snapshot or demo balances. Retrying the app load retries setup. Existing organization
|
||||
payments and pooled balances are never imported into customer history. This
|
||||
integration exposes the durable operations initiated through this BFF, with live
|
||||
provider reconciliation; independent inbound deposits/history ingestion and
|
||||
|
||||
@@ -302,32 +302,42 @@ that contradicts displayed balances or usage without explaining the fixtures.
|
||||
- Keep unrelated accounts/history accessible during a pending operation. Do not
|
||||
block the whole product behind an exchange spinner.
|
||||
|
||||
## Empty currency accounts (task #66)
|
||||
## Automatic currency accounts (task #72)
|
||||
|
||||
The shared empty-account message used on Accounts and transfer screens explains
|
||||
that no currency accounts have been set up and directs the customer to support
|
||||
to request setup. English and Russian no longer suggest that refreshing creates
|
||||
accounts or imply that automatic provisioning is underway. This follows the
|
||||
existing support guidance for missing funding and payout setup. The application
|
||||
has no configured support contact channel; the message therefore provides text
|
||||
guidance without a nonfunctional contact button or invented contact details.
|
||||
New customers receive RUB, USDT and USDC accounts through backend-owned setup
|
||||
during signup. Existing customers receive missing defaults on their next wallet
|
||||
load. The UI requires no account-creation form or support contact. During initial
|
||||
loading it announces that the accounts are being prepared. Failure shows one
|
||||
clear load error and a **Try again** action that reruns the same idempotent setup.
|
||||
An unexpected empty snapshot has its own setup-failure fallback, rather than
|
||||
being shown simultaneously with an error. A failed refresh retains existing
|
||||
cards and the stale-data warning. Account-not-found copy requires loaded data.
|
||||
|
||||
UX review: the copy names the missing resource and the next step, retains the
|
||||
existing wrapping text and accessible reading order, and does not alter loading,
|
||||
error or populated-state behavior. Existing manual refresh remains available for
|
||||
accounts provisioned externally. This copy-only change adds no controls or
|
||||
journey outcomes and requires no new analytics events. Existing transaction
|
||||
journey signals and their production measurement limitations below still apply;
|
||||
support resolution and external account provisioning are not measured in-app.
|
||||
The existing DTO → mapper → service → model → provider → UI boundaries remain
|
||||
intact. Account creation belongs to the backend/provider, and widgets invoke the
|
||||
existing provider refresh action. English and Russian use wrapping text and the
|
||||
existing accessible button pattern; status text uses a live region. Dedicated
|
||||
widget regressions cover loading, failure, retry and successful default accounts
|
||||
on Accounts, Top up, Exchange and Payout at 320px with 1.6× text. Native device and
|
||||
screen-reader QA remain a release check; tests do not claim physical-device QA.
|
||||
|
||||
Validation: `flutter gen-l10n`, `flutter analyze` in `frontend/app`,
|
||||
`make test-frontend` (217 tests), and `git diff --check` passed. No Dart source
|
||||
changed, so Dart formatting was not applicable. Existing responsive workspace
|
||||
tests cover Russian at 320px with enlarged text; this copy-only change does not
|
||||
add a dedicated empty-state rendering or native screen-reader test. No security
|
||||
scan was requested. Delivery: [task #66](https://git.sendico.io/tech/sxchnge/issues/66),
|
||||
branch `wallet-66`, [PR #68](https://git.sendico.io/tech/sxchnge/pulls/68).
|
||||
Merge and deployment remain separate.
|
||||
Measurement: `sxchnge_currency_accounts_setup_total{outcome="ready|failed"}` and
|
||||
`sxchnge_currency_accounts_setup_duration_seconds` cover the server setup attempt.
|
||||
`ready` is emitted only after all default bindings are confirmed, including
|
||||
idempotent completion of provider wallet/route setup for newly bound ledgers.
|
||||
Each signup/resend/wallet load is a separate attempt; a retry is not a new unique
|
||||
customer conversion. The failure fraction uses all attempts as its denominator;
|
||||
the histogram measures one attempt, not time across multiple browser sessions.
|
||||
No customer, ledger, currency, balance, credentials or form input is a metric
|
||||
label. These server metrics do not measure client abandonment or prove that a
|
||||
balance card was viewed. Existing transaction journey outcomes below are reused;
|
||||
no speculative button-click events are added.
|
||||
|
||||
Scope and rollout: [task #72](https://git.sendico.io/tech/sxchnge/issues/72), branch
|
||||
`wallet-72`, [task #72](https://git.sendico.io/tech/sxchnge/issues/72). The provider
|
||||
prerequisite and deployment order are documented in [payments](../payments.md).
|
||||
Merge and deployment remain separate. Final validation is recorded in the task
|
||||
and PR, including any transient failures and environmental blockers.
|
||||
|
||||
## Journey measurement plan
|
||||
|
||||
|
||||
Reference in new issue
Block a user