Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions __tests__/MigrationStrategy.nymGate.unit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { RPCMixnetIndicatorEnum } from '../app/walletBackend/enums/RPCMixnetIndi
import {
MixnetView,
deriveMixnetView,
} from '../app/walletBackend/transforms/mixnetPresenter';
} from '../app/walletBackend/transforms/mixnetView';
import {
mixnetConnecting,
mixnetLost,
Expand Down Expand Up @@ -80,7 +80,7 @@ describe('deriveNymGateState', () => {
});

test('fails only on the died and unknown keys, across every view', () => {
// Every view the presenter can emit: the four indicators and the failure
// Every view the transform can emit: the four indicators and the failure
// report, with and without the reconnect flag, with and without a held
// Enable tap.
const indicators = [
Expand Down
2 changes: 1 addition & 1 deletion __tests__/PriceFetcher.snapshot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { mockTranslate } from '../__mocks__/dataMocks/mockTranslate';
import { mockInfo } from '../__mocks__/dataMocks/mockInfo';
// test suite
describe('Component PriceFetcher - test', () => {
// The ring renders only while the store's surface verdict holds, so
// The ring renders only while the store's surface decision holds, so
// the driver mounts beside the fetcher exactly as LoadedApp does; the
// snapshot pins that consented state, not the empty render.
const state = { ...defaultAppContextLoaded };
Expand Down
2 changes: 1 addition & 1 deletion __tests__/Send.priceCta.unit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ beforeEach(() => {
surfaceActive: false,
});
// The health follows the priceDate each call site actually wires
// through, so an unwired row cannot pass by a blanket verdict.
// through, so an unwired row cannot pass by a blanket decision.
healthHook.mockImplementation(priceDate =>
priceDate === 0
? 'absent'
Expand Down
6 changes: 3 additions & 3 deletions __tests__/mixnetStatusKeys.unit.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
/**
* Evidence test for the PR 1343 review finding F10: the mixnet status
* keys were hand-copied as bare string literals in three modules with no
* shared, compiler-checked source. The presenter must export the closed
* shared, compiler-checked source. The transform must export the closed
* key set, and every view it derives must stay inside it.
*/
import {
MIXNET_STATUS_KEYS,
INITIAL_MIXNET_VIEW,
OFF_MIXNET_VIEW,
deriveMixnetView,
} from '../app/walletBackend/transforms/mixnetPresenter';
} from '../app/walletBackend/transforms/mixnetView';
import { RPCMixnetIndicatorEnum } from '../app/walletBackend/enums/RPCMixnetIndicatorEnum';

test('R10: the closed status-key set derives from the indicator enum', () => {
// No verbatim copy: the expectation is computed from the enum the wallet
// reports, plus the presenter's own failure key.
// reports, plus the transform's own failure key.
const derivedKeys = new Set([
...Object.values(RPCMixnetIndicatorEnum).map(s => `mixnet.status.${s}`),
'mixnet.status.unknown',
Expand Down
2 changes: 1 addition & 1 deletion __tests__/priceDisplay.ring.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ test('a refusing transport hides the ring for the same reason', () => {
}),
),
);
// The cadence is paused by the verdict; a ring filling toward a
// The cadence is paused by the policy; a ring filling toward a
// refresh that cannot come misleads exactly like the unconsented case.
expect(view.queryByTestId('pricefetcher.ring')).toBeNull();
});
18 changes: 9 additions & 9 deletions __tests__/priceStore.contract.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import {
INITIAL_MIXNET_VIEW,
MIXNET_STATUS_KEYS,
MixnetView,
transportDisposition,
} from '../app/walletBackend/transforms/mixnetPresenter';
fetchPolicy,
} from '../app/walletBackend/transforms/mixnetView';

const price = getZecPrice as jest.MockedFunction<typeof getZecPrice>;

Expand Down Expand Up @@ -152,14 +152,14 @@ test('the ready follow-up never re-arms itself', async () => {
expect(price).toHaveBeenCalledTimes(4);
});

test('every status key classifies under the disposition switch', () => {
const dispositions = MIXNET_STATUS_KEYS.map(key => transportDisposition(key));
dispositions.forEach(d =>
expect(['refusing', 'possibleBootstrap', 'serving']).toContain(d),
test('every status key classifies under the fetch-policy switch', () => {
const policies = MIXNET_STATUS_KEYS.map(key => fetchPolicy(key));
policies.forEach(p =>
expect(['refusing', 'possibleBootstrap', 'serving']).toContain(p),
);
expect(dispositions).toContain('refusing');
expect(dispositions).toContain('possibleBootstrap');
expect(dispositions).toContain('serving');
expect(policies).toContain('refusing');
expect(policies).toContain('possibleBootstrap');
expect(policies).toContain('serving');
});

test('the driver writes deps when an input moves, not per render', async () => {
Expand Down
6 changes: 3 additions & 3 deletions __tests__/priceStore.lifecycle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { getZecPrice } from '../app/walletBackend';
import {
INITIAL_MIXNET_VIEW,
MixnetView,
} from '../app/walletBackend/transforms/mixnetPresenter';
} from '../app/walletBackend/transforms/mixnetView';

const price = getZecPrice as jest.MockedFunction<typeof getZecPrice>;

Expand Down Expand Up @@ -273,7 +273,7 @@ test('a follow-up arriving mid-flight fires after the flight, not never', async
expect(price.mock.calls.length).toBeGreaterThan(inFlight + 1);
});

test('a real transport verdict disarms the follow-up', async () => {
test('a real transport policy disarms the follow-up', async () => {
price.mockResolvedValue({ price: -1, error: 'refused' });
const setZecPrice = jest.fn();
seedDeps(setZecPrice);
Expand Down Expand Up @@ -493,7 +493,7 @@ test('a transient unknown poll does not drop the armed follow-up', async () => {
await waitFor(() => expect(price).toHaveBeenCalledTimes(2)); // refused: arms

view.rerender(fetcherUi(makeCtx({ mixnetView: UNKNOWN_VIEW }), setZecPrice));
await flush(); // one failed status poll, not a transport verdict
await flush(); // one failed status poll, not a transport policy
view.rerender(fetcherUi(makeCtx({ mixnetView: READY_VIEW }), setZecPrice));
await flush();

Expand Down
4 changes: 2 additions & 2 deletions __tests__/priceStore.nativeCall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
import { SelectServerEnum } from '../app/AppState';
import { getZecPrice } from '../app/walletBackend';
import { mockInfo } from '../__mocks__/dataMocks/mockInfo';
import { MixnetView } from '../app/walletBackend/transforms/mixnetPresenter';
import { MixnetView } from '../app/walletBackend/transforms/mixnetView';

const price = getZecPrice as jest.MockedFunction<typeof getZecPrice>;

Expand Down Expand Up @@ -195,7 +195,7 @@ test("a refusal under a transient 'unknown' arms the follow-up", async () => {
const refusedUnderUnknown = price.mock.calls.length;
expect(refusedUnderUnknown).toBeGreaterThan(0);

// 'unknown' is one failed status poll, not a verdict, on the arm path
// 'unknown' is one failed status poll, not a policy, on the arm path
// exactly as on the drop path: ready must fire the follow-up now, not
// a full tick later.
view.rerender(surfaceUi(makeCtx({ mixnetView: READY_VIEW }), setZecPrice));
Expand Down
2 changes: 1 addition & 1 deletion __tests__/priceStore.recovery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
import { SelectServerEnum } from '../app/AppState';
import { getZecPrice } from '../app/walletBackend';
import { mockInfo } from '../__mocks__/dataMocks/mockInfo';
import { MixnetView } from '../app/walletBackend/transforms/mixnetPresenter';
import { MixnetView } from '../app/walletBackend/transforms/mixnetView';

const price = getZecPrice as jest.MockedFunction<typeof getZecPrice>;

Expand Down
2 changes: 1 addition & 1 deletion __tests__/priceStore.trafficGuards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
INITIAL_MIXNET_VIEW,
OFF_MIXNET_VIEW,
MixnetView,
} from '../app/walletBackend/transforms/mixnetPresenter';
} from '../app/walletBackend/transforms/mixnetView';

const DIED_VIEW: MixnetView = {
statusKey: 'mixnet.status.died',
Expand Down
2 changes: 1 addition & 1 deletion __tests__/priceStore.wedgeGuards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
} from '../app/context';
import { ChainNameEnum, SelectServerEnum } from '../app/AppState';
import { getZecPrice } from '../app/walletBackend';
import { MixnetView } from '../app/walletBackend/transforms/mixnetPresenter';
import { MixnetView } from '../app/walletBackend/transforms/mixnetView';
import { mockInfo } from '../__mocks__/dataMocks/mockInfo';

const price = getZecPrice as jest.MockedFunction<typeof getZecPrice>;
Expand Down
4 changes: 2 additions & 2 deletions __tests__/walletBackend.mixnetCoordinator.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {
RECONNECT_BASE_MILLIS,
STEADY_POLL_MILLIS,
} from '../app/walletBackend/modules/MixnetCoordinator';
import { deriveMixnetView } from '../app/walletBackend/transforms/mixnetPresenter';
import { MixnetView } from '../app/walletBackend/transforms/mixnetPresenter';
import { deriveMixnetView } from '../app/walletBackend/transforms/mixnetView';
import { MixnetView } from '../app/walletBackend/transforms/mixnetView';

jest.mock('../app/RPCModule', () =>
require('../__mocks__/rpcModuleProxy').rpcModuleProxyMock(),
Expand Down
2 changes: 1 addition & 1 deletion app/AppState/AppContextLoaded.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import TransparentAddressClass from './classes/TransparentAddressClass';
import { ScreenEnum } from './enums/ScreenEnum';
import { RPCPerformanceLevelEnum } from '../walletBackend/enums/RPCPerformanceLevelEnum';
import { BlockExplorerEnum } from './enums/BlockExplorerEnum';
import { MixnetView } from '../walletBackend/transforms/mixnetPresenter';
import { MixnetView } from '../walletBackend/transforms/mixnetView';

export default interface AppContextLoaded {
netInfo: NetInfoType;
Expand Down
2 changes: 1 addition & 1 deletion app/LoadedApp/LoadedApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ import {
INITIAL_MIXNET_VIEW,
OFF_MIXNET_VIEW,
MixnetView,
} from '../walletBackend/transforms/mixnetPresenter';
} from '../walletBackend/transforms/mixnetView';
import {
startMixnetTransport,
stopMixnetTransport,
Expand Down
2 changes: 1 addition & 1 deletion app/walletBackend/config/WalletBackendConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
StartMixnetTransport,
StopMixnetTransport,
} from '../modules/MixnetCoordinator';
import { MixnetView } from '../transforms/mixnetPresenter';
import { MixnetView } from '../transforms/mixnetView';

/**
* All callbacks and settings required by WalletBackend and its sub-services.
Expand Down
4 changes: 2 additions & 2 deletions app/walletBackend/modules/MixnetCoordinator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* the platform owns it: on Android the UniFFI proxy shim (step 3 of the
* critical path) supplies it; tests supply a stub. This coordinator owns
* cadence and policy only — every payload decision lives in the pure
* transforms, and every screen projection in the pure presenter.
* transforms, and every screen projection in the pure transform.
*
* Cadence follows the SyncCoordinator idiom: one interval, a lock flag so
* a slow poll is never enqueued twice, and an onChange callback that
Expand All @@ -28,7 +28,7 @@ import {
describeRejection,
vetPolledStatus,
} from '../transforms/mixnetTransform';
import { MixnetView, deriveMixnetView } from '../transforms/mixnetPresenter';
import { MixnetView, deriveMixnetView } from '../transforms/mixnetView';
import {
attachMixnet,
disableMixnet,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import { MixnetDetailReport, MixnetStatusReport } from './mixnetTransform';

/**
* What the user may do about the current mixnet state: nothing, wait for
* the bootstrap, or re-enable a lost transport. A closed union so screens
* must render every case the policy can produce.
* the bootstrap, or re-enable a transport.
*/
export type MixnetRecoveryAction = 'none' | 'wait' | 'reenable';

/** One member of the closed status-key set: an indicator the wallet reports, or this presenter's own `unknown` failure key. */
/** One member of the closed status-key set: an indicator the wallet reports, or this transform's own `unknown` failure key. */
export type MixnetStatusKey =
`mixnet.status.${`${RPCMixnetIndicatorEnum}` | 'unknown'}`;

Expand All @@ -20,14 +19,14 @@ export const MIXNET_STATUS_KEYS: readonly MixnetStatusKey[] = [
'mixnet.status.unknown',
];

/** How the transport disposes a price fetch. */
export type MixnetTransportDisposition =
/** What the transport will do with a price fetch. */
export type FetchPolicy =
'refusing' | 'possibleBootstrap' | 'serving';

/** Classifies a status key exhaustively. */
export function transportDisposition(
export function fetchPolicy(
key: MixnetStatusKey,
): MixnetTransportDisposition {
): FetchPolicy {
switch (key) {
case 'mixnet.status.died':
return 'refusing';
Expand All @@ -44,7 +43,7 @@ export function transportDisposition(
* The screen-facing projection of the mixnet state. `statusKey` is a
* translation key (`mixnet.status.*`), never display English; `narration`
* is the live bootstrap line when one exists; `sendBlocked` is the
* fail-closed verdict a send screen must respect — `true` in every state
* fail-closed status a send screen must respect — `true` in every state
* except an explicit `off` (deliberate clearnet consent) or `ready`.
*/
export type MixnetView = {
Expand Down
2 changes: 1 addition & 1 deletion components/Components/PriceFetcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const PriceFetcher: React.FunctionComponent<PriceFetcherProps> = ({
usePriceFetcherStore();
const health = usePriceHealth(zecPrice.date);

// The store's own verdict decides visibility: without the consent,
// The store's own decision governs visibility: without the consent,
// the market, or a serving transport no cadence exists, and a ring
// counting down to a refresh that cannot come would mislead, so
// render nothing at all.
Expand Down
26 changes: 13 additions & 13 deletions components/Components/priceFetcherStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { AppState, NativeEventSubscription } from 'react-native';
import { getZecPrice } from '../../app/walletBackend';
import {
MixnetStatusKey,
transportDisposition,
} from '../../app/walletBackend/transforms/mixnetPresenter';
fetchPolicy,
} from '../../app/walletBackend/transforms/mixnetView';

/**
* Shared, singleton state for the price surface's fetch lifecycle.
Expand All @@ -16,7 +16,7 @@ import {
* currency never decides what may be fetched; PriceFetcher and
* usePriceFetcherStore only observe. The store owns the whole lifecycle:
* - ONE auto-refresh timer while the driver is attached, the gate-open
* foreground holds, and the transport is not a refusing verdict
* foreground holds, and the transport is not a refusing policy
* ('died'): each fetch schedules the next at a uniform random delay
* of five to ten minutes. A background transition pauses the
* cadence, and iOS 'inactive' (Control Center, the app's own Face ID
Expand All @@ -28,7 +28,7 @@ import {
* the last start or last success yield to the cadence.
* - The ready follow-up: an unattended fetch refused during bootstrap
* arms a one-shot fetch that fires when the Indicator turns ready.
* It is dropped on a background transition and on a 'died' verdict,
* It is dropped on a background transition and on a 'died' policy,
* survives an in-flight fetch, and a transient 'unknown' status poll
* never drops it.
* - No snackbars. A failure leaves the last price standing; the stale
Expand Down Expand Up @@ -67,7 +67,7 @@ type PriceSurfaceSnapshot = {
loading: boolean;
nextFetchAt: number;
nextFetchDelayMs: number;
// The store's own render verdict, so no view re-derives (and drifts
// The store's own render decision, so no view re-derives (and drifts
// from) surfaceMayFetch.
surfaceActive: boolean;
};
Expand Down Expand Up @@ -137,13 +137,13 @@ function clearAuto(): void {
emit();
}

// A transport verdict under which the wallet refuses every price fetch
// A transport policy under which the wallet refuses every price fetch
// by the route rule, so attempting is pure waste; the classification is
// the presenter's exhaustive switch, which a new indicator breaks.
// fetchPolicy's exhaustive switch, which a new indicator breaks.
function transportRefuses(): boolean {
return (
deps !== undefined &&
transportDisposition(deps.mixnetStatusKey) === 'refusing'
fetchPolicy(deps.mixnetStatusKey) === 'refusing'
);
}

Expand Down Expand Up @@ -231,10 +231,10 @@ async function boundedPrice(): Promise<number> {
}

// A status that could still be a bootstrap in progress: 'unknown' is
// one failed status poll, not a verdict, on the arm path exactly as on
// one failed status poll, not a policy, on the arm path exactly as on
// the drop path in pump().
function statusCouldBeBootstrap(key: MixnetStatusKey): boolean {
return transportDisposition(key) === 'possibleBootstrap';
return fetchPolicy(key) === 'possibleBootstrap';
}

// A refusal may arm the ready follow-up from every launch path except
Expand Down Expand Up @@ -278,7 +278,7 @@ async function doFetch(mayArmFollowUp: boolean): Promise<void> {
if (price > 0) {
// The traffic was already spent under the launch's consent, so
// the value is recorded even where a new fetch would now be
// refused (a background hop, a moved verdict): discarding it
// refused (a background hop, a moved policy): discarding it
// would only buy a second identical fetch later.
followUpArmed = false;
entryPending = false; // a fresh price satisfies a pending return
Expand Down Expand Up @@ -331,8 +331,8 @@ function pump(): void {
followUpArmed = false;
doFetch(false).catch(() => {});
} else if (transportRefuses()) {
// A real transport verdict ends the bootstrap the arm belonged to.
// 'unknown' is one failed status poll, not a verdict, and a
// A real transport policy ends the bootstrap the arm belonged to.
// 'unknown' is one failed status poll, not a policy, and a
// bootstrap's polls are flakiest exactly while the arm matters, so
// both it and 'bootstrapping' keep the arm standing.
followUpArmed = false;
Expand Down
2 changes: 1 addition & 1 deletion components/Header/components/MixnetIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
import { Animated, Easing, StyleSheet, View } from 'react-native';
import Svg, { Rect } from 'react-native-svg';
import NymOn from '../../../assets/img/nym-on.svg';
import { MixnetStatusKey } from '../../../app/walletBackend/transforms/mixnetPresenter';
import { MixnetStatusKey } from '../../../app/walletBackend/transforms/mixnetView';

const HALO_GREEN = '#07FF94';
const HALO_CORAL = '#FF6F61';
Expand Down
2 changes: 1 addition & 1 deletion components/Header/components/SyncStatusBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
TranslateType,
} from '../../../app/AppState';
import NetInfoType from '../../../app/AppState/types/NetInfoType';
import { MixnetView } from '../../../app/walletBackend/transforms/mixnetPresenter';
import { MixnetView } from '../../../app/walletBackend/transforms/mixnetView';
import FadeText from '../../Components/FadeText';
import NymOn from '../../../assets/img/nym-on.svg';
import MixnetIcon, { mixnetPhase } from './MixnetIcon';
Expand Down
Loading
Loading