@stridge/kit 0.1.0-alpha.30 → 0.1.0-alpha.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/_internal/drivers/stridge/index.d.ts +2 -2
  2. package/dist/_internal/drivers/stridge/index.js +1 -1
  3. package/dist/deposit/compound/index.d.ts +1 -1
  4. package/dist/drivers/stridge/createStridgeDepositDriver.js +1 -1
  5. package/dist/drivers/stridge/createStridgeWithdrawDriver.d.ts +16 -1
  6. package/dist/drivers/stridge/createStridgeWithdrawDriver.js +1 -1
  7. package/dist/drivers/stridge/types.d.ts +13 -10
  8. package/dist/drivers/stridge/types.js +1 -1
  9. package/dist/drivers/stridge-mock/createStridgeMockDriver.d.ts +2 -2
  10. package/dist/drivers/stridge-mock/createStridgeMockDriver.js +1 -1
  11. package/dist/drivers/stridge-mock/createStridgeMockWithdrawDriver.d.ts +12 -0
  12. package/dist/drivers/stridge-mock/createStridgeMockWithdrawDriver.js +1 -1
  13. package/dist/drivers/stridge-mock/fixtures.d.ts +6 -6
  14. package/dist/drivers/stridge-mock/fixtures.js +1 -1
  15. package/dist/events/bus/createBus.d.ts +7 -0
  16. package/dist/events/bus/createBus.js +1 -0
  17. package/dist/events/bus/flowIdRegistry.d.ts +17 -0
  18. package/dist/events/bus/flowIdRegistry.js +1 -0
  19. package/dist/events/bus/index.js +1 -0
  20. package/dist/events/bus/metadata.js +1 -0
  21. package/dist/events/context.js +1 -0
  22. package/dist/events/emit/index.js +1 -0
  23. package/dist/events/emit/mapFailure.js +1 -0
  24. package/dist/events/emit/useDepositEmissions.js +1 -0
  25. package/dist/events/emit/useKitEmitter.js +1 -0
  26. package/dist/events/emit/useWithdrawEmissions.js +1 -0
  27. package/dist/events/hooks/index.d.ts +6 -0
  28. package/dist/events/hooks/index.js +1 -0
  29. package/dist/events/hooks/useCurrentFlowId.d.ts +6 -0
  30. package/dist/events/hooks/useCurrentFlowId.js +1 -0
  31. package/dist/events/hooks/useStableHandler.js +1 -0
  32. package/dist/events/hooks/useStridgeEvent.d.ts +8 -0
  33. package/dist/events/hooks/useStridgeEvent.js +1 -0
  34. package/dist/events/hooks/useStridgeEventBus.d.ts +33 -0
  35. package/dist/events/hooks/useStridgeEventBus.js +1 -0
  36. package/dist/events/hooks/useStridgeEvents.d.ts +6 -0
  37. package/dist/events/hooks/useStridgeEvents.js +1 -0
  38. package/dist/events/hooks/useStridgeFlowEvent.d.ts +8 -0
  39. package/dist/events/hooks/useStridgeFlowEvent.js +1 -0
  40. package/dist/events/hooks/useStridgeFlowEvents.d.ts +6 -0
  41. package/dist/events/hooks/useStridgeFlowEvents.js +1 -0
  42. package/dist/events/index.d.ts +14 -0
  43. package/dist/events/index.js +1 -0
  44. package/dist/events/publish.js +1 -0
  45. package/dist/events/types/deposit.d.ts +235 -0
  46. package/dist/events/types/envelope.d.ts +145 -0
  47. package/dist/events/types/index.d.ts +31 -0
  48. package/dist/events/types/kit.d.ts +23 -0
  49. package/dist/events/types/withdraw.d.ts +150 -0
  50. package/dist/flows/deposit/dialog/DepositDialog.d.ts +14 -81
  51. package/dist/flows/deposit/dialog/DepositDialog.js +1 -1
  52. package/dist/flows/deposit/driver/payloads.d.ts +10 -4
  53. package/dist/flows/deposit/driver/transformers/balanceToBalancesPayload.js +1 -1
  54. package/dist/flows/deposit/driver/transformers/startToAddressesPayload.js +1 -1
  55. package/dist/flows/deposit/driver/transformers/startToTargetPayload.js +1 -1
  56. package/dist/flows/deposit/widgets/amount-entry/AmountEntry.d.ts +1 -1
  57. package/dist/flows/deposit/widgets/amount-entry/AmountEntry.js +1 -1
  58. package/dist/flows/deposit/widgets/amount-entry/footerIntent.js +1 -0
  59. package/dist/flows/deposit/widgets/confirm-deposit/ConfirmDeposit.js +1 -1
  60. package/dist/flows/deposit/widgets/transfer-crypto/TransferCrypto.js +1 -1
  61. package/dist/flows/deposit/widgets/transfer-crypto/compound/TransferCrypto.d.ts +1 -1
  62. package/dist/flows/withdraw/dialog/WithdrawDialog.d.ts +27 -109
  63. package/dist/flows/withdraw/dialog/WithdrawDialog.js +1 -1
  64. package/dist/flows/withdraw/driver/types.d.ts +16 -2
  65. package/dist/flows/withdraw/orchestrator/controller.js +1 -1
  66. package/dist/flows/withdraw/orchestrator/types.d.ts +18 -1
  67. package/dist/flows/withdraw/widgets/withdraw-form/WithdrawForm.d.ts +5 -13
  68. package/dist/flows/withdraw/widgets/withdraw-form/WithdrawForm.js +1 -1
  69. package/dist/flows/withdraw/widgets/withdraw-form/validation.js +1 -1
  70. package/dist/i18n/locales/ar.js +1 -1
  71. package/dist/i18n/locales/es.js +1 -1
  72. package/dist/i18n/locales/source-keys.d.ts +1 -1
  73. package/dist/index.d.ts +9 -1
  74. package/dist/index.js +1 -1
  75. package/dist/package.js +1 -1
  76. package/dist/shared/support/SupportLink.js +1 -1
  77. package/dist/shared/terms/TermsLink.js +1 -1
  78. package/dist/stridge/StridgeProvider.d.ts +25 -3
  79. package/dist/stridge/StridgeProvider.js +1 -1
  80. package/package.json +7 -3
  81. package/dist/flows/withdraw/dialog/WithdrawDialogEventsContext.d.ts +0 -36
  82. package/dist/flows/withdraw/dialog/WithdrawDialogEventsContext.js +0 -1
@@ -0,0 +1 @@
1
+ "use client";import{StridgeEventsContext as e}from"../context.js";import{use as t,useMemo as n}from"react";function r(){let r=t(e);return n(()=>r?{subscribeToFlow:r.bus.subscribeToFlow,subscribeToFlowEvent:r.bus.subscribeToFlowEvent,subscribeToAll:r.bus.subscribeToAll,subscribeToEvent:r.bus.subscribeToEvent}:null,[r])}export{r as useStridgeEventBus};
@@ -0,0 +1,6 @@
1
+ import { StridgeEvent } from "../types/index.js";
2
+
3
+ //#region src/events/hooks/useStridgeEvents.d.ts
4
+ declare function useStridgeEvents(handler: (event: StridgeEvent) => void): void;
5
+ //#endregion
6
+ export { useStridgeEvents };
@@ -0,0 +1 @@
1
+ "use client";import{StridgeEventsContext as e}from"../context.js";import{useStableHandler as t}from"./useStableHandler.js";import{use as n,useEffect as r}from"react";function i(i){let a=n(e),o=t(i);r(()=>{if(a)return a.bus.subscribeToAll(e=>o.current(e))},[a,o])}export{i as useStridgeEvents};
@@ -0,0 +1,8 @@
1
+ import { FlowEvent } from "../types/index.js";
2
+
3
+ //#region src/events/hooks/useStridgeFlowEvent.d.ts
4
+ declare function useStridgeFlowEvent<TType extends FlowEvent["type"]>(type: TType, handler: (event: Extract<FlowEvent, {
5
+ type: TType;
6
+ }>) => void): void;
7
+ //#endregion
8
+ export { useStridgeFlowEvent };
@@ -0,0 +1 @@
1
+ "use client";import{StridgeEventsContext as e}from"../context.js";import{useStableHandler as t}from"./useStableHandler.js";import{use as n,useEffect as r}from"react";function i(i,a){let o=n(e),s=t(a);r(()=>{if(o)return o.bus.subscribeToFlowEvent(i,e=>s.current(e))},[o,s,i])}export{i as useStridgeFlowEvent};
@@ -0,0 +1,6 @@
1
+ import { FlowEvent } from "../types/index.js";
2
+
3
+ //#region src/events/hooks/useStridgeFlowEvents.d.ts
4
+ declare function useStridgeFlowEvents(handler: (event: FlowEvent) => void): void;
5
+ //#endregion
6
+ export { useStridgeFlowEvents };
@@ -0,0 +1 @@
1
+ "use client";import{StridgeEventsContext as e}from"../context.js";import{useStableHandler as t}from"./useStableHandler.js";import{use as n,useEffect as r}from"react";function i(i){let a=n(e),o=t(i);r(()=>{if(a)return a.bus.subscribeToFlow(e=>o.current(e))},[a,o])}export{i as useStridgeFlowEvents};
@@ -0,0 +1,14 @@
1
+ import { FlowIdKey } from "./bus/flowIdRegistry.js";
2
+ import { useCurrentFlowId } from "./hooks/useCurrentFlowId.js";
3
+ import { FailureCode, FailurePayloadBase, StridgeEventBase, StridgeEventFlow, StridgeEventTier } from "./types/envelope.js";
4
+ import { DepositAmountChangedEvent, DepositAmountSubmittedEvent, DepositAssetClickedEvent, DepositBackClickedEvent, DepositCancelPhase, DepositCancelledEvent, DepositClosedEvent, DepositConfirmClickedEvent, DepositEvent, DepositFlowEvent, DepositMaxClickedEvent, DepositMethodClickedEvent, DepositOpenedEvent, DepositQuoteExpiredEvent, DepositQuoteFailedEvent, DepositQuoteRequestInput, DepositQuoteRequestedEvent, DepositQuoteResolvedEvent, DepositSettlementFailedEvent, DepositSettlementFailurePayload, DepositSettlementProgressedEvent, DepositSettlementResumedEvent, DepositSettlementSucceededEvent, DepositStepChangedEvent, DepositSubmissionBroadcastEvent, DepositSubmissionConfirmedEvent, DepositSubmissionDeclinedEvent, DepositSubmissionFailedEvent, DepositTransferAddressCopiedEvent, DepositTransferChainChangedEvent, DepositTransferTokenChangedEvent, DepositUiEvent } from "./types/deposit.js";
5
+ import { KitEvent, KitSupportClickedEvent, KitTermsClickedEvent } from "./types/kit.js";
6
+ import { WithdrawAmountChangedEvent, WithdrawBreakdownClickedEvent, WithdrawCancelPhase, WithdrawCancelledEvent, WithdrawClosedEvent, WithdrawEvent, WithdrawFlowEvent, WithdrawMaxClickedEvent, WithdrawOpenedEvent, WithdrawQuoteExpiredEvent, WithdrawQuoteFailedEvent, WithdrawQuoteRequestedEvent, WithdrawQuoteResolvedEvent, WithdrawReceiveChainChangedEvent, WithdrawReceiveTokenChangedEvent, WithdrawRecipientChangedEvent, WithdrawSettlementFailedEvent, WithdrawSettlementFailurePayload, WithdrawSettlementProgressedEvent, WithdrawSettlementSucceededEvent, WithdrawStepChangedEvent, WithdrawSubmissionBroadcastEvent, WithdrawSubmissionConfirmedEvent, WithdrawSubmissionDeclinedEvent, WithdrawSubmissionFailedEvent, WithdrawSubmitClickedEvent, WithdrawUiEvent } from "./types/withdraw.js";
7
+ import { FlowEvent, FlowEventType, StridgeEvent, StridgeEventType, UiEvent, UiEventType } from "./types/index.js";
8
+ import { useStridgeEvent } from "./hooks/useStridgeEvent.js";
9
+ import { EventHandler } from "./bus/createBus.js";
10
+ import { PublicStridgeEventBus, useStridgeEventBus } from "./hooks/useStridgeEventBus.js";
11
+ import { useStridgeEvents } from "./hooks/useStridgeEvents.js";
12
+ import { useStridgeFlowEvent } from "./hooks/useStridgeFlowEvent.js";
13
+ import { useStridgeFlowEvents } from "./hooks/useStridgeFlowEvents.js";
14
+ export { type DepositAmountChangedEvent, type DepositAmountSubmittedEvent, type DepositAssetClickedEvent, type DepositBackClickedEvent, type DepositCancelPhase, type DepositCancelledEvent, type DepositClosedEvent, type DepositConfirmClickedEvent, type DepositEvent, type DepositFlowEvent, type DepositMaxClickedEvent, type DepositMethodClickedEvent, type DepositOpenedEvent, type DepositQuoteExpiredEvent, type DepositQuoteFailedEvent, type DepositQuoteRequestInput, type DepositQuoteRequestedEvent, type DepositQuoteResolvedEvent, type DepositSettlementFailedEvent, type DepositSettlementFailurePayload, type DepositSettlementProgressedEvent, type DepositSettlementResumedEvent, type DepositSettlementSucceededEvent, type DepositStepChangedEvent, type DepositSubmissionBroadcastEvent, type DepositSubmissionConfirmedEvent, type DepositSubmissionDeclinedEvent, type DepositSubmissionFailedEvent, type DepositTransferAddressCopiedEvent, type DepositTransferChainChangedEvent, type DepositTransferTokenChangedEvent, type DepositUiEvent, type EventHandler, type FailureCode, type FailurePayloadBase, type FlowEvent, type FlowEventType, type FlowIdKey, type KitEvent, type KitSupportClickedEvent, type KitTermsClickedEvent, type PublicStridgeEventBus, type StridgeEvent, type StridgeEventBase, type StridgeEventFlow, type StridgeEventTier, type StridgeEventType, type UiEvent, type UiEventType, type WithdrawAmountChangedEvent, type WithdrawBreakdownClickedEvent, type WithdrawCancelPhase, type WithdrawCancelledEvent, type WithdrawClosedEvent, type WithdrawEvent, type WithdrawFlowEvent, type WithdrawMaxClickedEvent, type WithdrawOpenedEvent, type WithdrawQuoteExpiredEvent, type WithdrawQuoteFailedEvent, type WithdrawQuoteRequestedEvent, type WithdrawQuoteResolvedEvent, type WithdrawReceiveChainChangedEvent, type WithdrawReceiveTokenChangedEvent, type WithdrawRecipientChangedEvent, type WithdrawSettlementFailedEvent, type WithdrawSettlementFailurePayload, type WithdrawSettlementProgressedEvent, type WithdrawSettlementSucceededEvent, type WithdrawStepChangedEvent, type WithdrawSubmissionBroadcastEvent, type WithdrawSubmissionConfirmedEvent, type WithdrawSubmissionDeclinedEvent, type WithdrawSubmissionFailedEvent, type WithdrawSubmitClickedEvent, type WithdrawUiEvent, useCurrentFlowId, useStridgeEvent, useStridgeEventBus, useStridgeEvents, useStridgeFlowEvent, useStridgeFlowEvents };
@@ -0,0 +1 @@
1
+ import{useCurrentFlowId as e}from"./hooks/useCurrentFlowId.js";import{useStridgeEvent as t}from"./hooks/useStridgeEvent.js";import{useStridgeEventBus as n}from"./hooks/useStridgeEventBus.js";import{useStridgeEvents as r}from"./hooks/useStridgeEvents.js";import{useStridgeFlowEvent as i}from"./hooks/useStridgeFlowEvent.js";import{useStridgeFlowEvents as a}from"./hooks/useStridgeFlowEvents.js";import"./hooks/index.js";export{e as useCurrentFlowId,t as useStridgeEvent,n as useStridgeEventBus,r as useStridgeEvents,i as useStridgeFlowEvent,a as useStridgeFlowEvents};
@@ -0,0 +1 @@
1
+ function e({bus:e,flowIds:t,metadata:n},r){let i=null;if(r.flow!==`kit`&&(i=t.current(r.flow),i===null)){process.env.NODE_ENV!==`production`&&console.warn(`[stridge/kit] tried to emit "${r.type}" but no active "${r.flow}" flow — the event was dropped. This usually means an emit fired before "opened" or after the terminal event.`);return}let a=r.flow===`kit`?{}:n.read(r.flow),o={type:r.type,flow:r.flow,tier:r.tier,timestamp:Date.now(),flowId:i,payload:r.payload,metadata:a};e.emit(o)}function t(t,n,i,a){r(n,a.flow,`openFlowSession`),t.flowIds.open(n),t.metadata.snapshot(n,i),e(t,{...a,flow:n})}function n(t,n,i){r(n,i.flow,`closeFlowSession`),e(t,{...i,flow:n}),t.flowIds.close(n),t.metadata.clear(n)}function r(e,t,n){process.env.NODE_ENV!==`production`&&e!==t&&console.error(`[stridge/kit] ${n}() called with flow="${e}" but partial.flow="${t}". Override applied (envelope will carry "${e}") but this is a sign of a copy-paste bug in the emit site.`)}export{n as closeFlowSession,t as openFlowSession,e as publishEvent};
@@ -0,0 +1,235 @@
1
+ import { SettlementFailureKind, TxRef } from "../../shared/driver/types.js";
2
+ import { BalanceItemPayload, QuotePayload, SettlementPendingPayload, SettlementSuccessPayload } from "../../flows/deposit/driver/payloads.js";
3
+ import { DepositMethod, DepositStateName, ResolvedOpenInput } from "../../flows/deposit/orchestrator/types.js";
4
+ import { TransferCryptoChain, TransferCryptoToken } from "../../flows/deposit/widgets/transfer-crypto/compound/types.js";
5
+ import { FailurePayloadBase, StridgeEventBase } from "./envelope.js";
6
+
7
+ //#region src/events/types/deposit.d.ts
8
+ /**
9
+ * Orchestrator-level input the kit assembled to ask the driver for a deposit quote. Mirrors
10
+ * the shape of {@link import("#/flows/withdraw/driver").RequestWithdrawalQuoteInput} for the
11
+ * deposit side — wrapping the request fields in a single `input` field keeps the `payload`
12
+ * shape symmetric across flows so generic analytics handlers can write
13
+ * `track("quote_requested", e.payload.input)` for both flows.
14
+ */
15
+ interface DepositQuoteRequestInput {
16
+ /** Source-side asset the user picked on the AssetPicker step. */
17
+ asset: BalanceItemPayload;
18
+ /** Send amount in display units. */
19
+ amount: number;
20
+ }
21
+ /**
22
+ * Phase the deposit flow was in when it was cancelled. Lets consumers distinguish "user
23
+ * abandoned at amount entry" from "user abandoned during processing wait" without parsing
24
+ * step names.
25
+ */
26
+ type DepositCancelPhase = "quoting" | "confirming" | "submitting" | "processing" | "unknown";
27
+ /**
28
+ * Settlement failure variant — extends the base with settlement-specific structure
29
+ * (typed `kind`, optional `txHash`) when the failure originates from the gateway's
30
+ * settlement entity rather than from a generic orchestrator path.
31
+ */
32
+ interface DepositSettlementFailurePayload extends FailurePayloadBase {
33
+ /**
34
+ * Driver-classified failure kind for downstream branching. Bounded enum so consumers can
35
+ * `switch (e.payload.kind)` exhaustively. The kit also escalates FSM-level failures with
36
+ * `kind: "unknown"` when no settlement-specific classification applies.
37
+ */
38
+ kind: SettlementFailureKind;
39
+ /** On-chain transaction hash, when one was successfully broadcast before settlement failed. */
40
+ txHash?: TxRef;
41
+ }
42
+ /**
43
+ * Orchestrator asked the driver for a quote — either the first request for this asset/amount
44
+ * pair or a regeneration after expiry or signature decline. The payload carries the inputs
45
+ * the orchestrator used so consumers can correlate request → response.
46
+ */
47
+ type DepositQuoteRequestedEvent = StridgeEventBase<"deposit.quote.requested", "deposit", "flow", {
48
+ input: DepositQuoteRequestInput;
49
+ }>;
50
+ /**
51
+ * Driver returned a successful quote and the orchestrator transitioned to `ready`. Payload is
52
+ * the full quote entity; reflect-then-render is safe (the orchestrator will not regenerate
53
+ * silently between this event and the next user action unless the quote expires).
54
+ */
55
+ type DepositQuoteResolvedEvent = StridgeEventBase<"deposit.quote.resolved", "deposit", "flow", {
56
+ quote: QuotePayload;
57
+ }>;
58
+ /**
59
+ * Quote fetch failed. Payload is the standard {@link FailurePayloadBase} — same shape as every
60
+ * other `*.failed` event so generic error handlers work without per-event branching.
61
+ */
62
+ type DepositQuoteFailedEvent = StridgeEventBase<"deposit.quote.failed", "deposit", "flow", FailurePayloadBase>;
63
+ /**
64
+ * Active quote went stale (TTL elapsed) before the user could submit, and the orchestrator
65
+ * silently started regenerating it. Payload is empty — the next `deposit.quote.resolved`
66
+ * carries the replacement quote.
67
+ */
68
+ type DepositQuoteExpiredEvent = StridgeEventBase<"deposit.quote.expired", "deposit", "flow", Record<string, never>>;
69
+ /**
70
+ * Wallet broadcast the deposit transaction and the orchestrator transitioned into
71
+ * `processing`. The on-chain tx hash is now stable; settlement polling has started.
72
+ */
73
+ type DepositSubmissionBroadcastEvent = StridgeEventBase<"deposit.submission.broadcast", "deposit", "flow", {
74
+ tx: TxRef;
75
+ }>;
76
+ /**
77
+ * User refused the wallet signature prompt. Distinct from {@link DepositSubmissionFailedEvent} —
78
+ * declining is a user choice, not an error. The orchestrator regenerates the quote and lands
79
+ * the user back on the confirm step.
80
+ */
81
+ type DepositSubmissionDeclinedEvent = StridgeEventBase<"deposit.submission.declined", "deposit", "flow", Record<string, never>>;
82
+ /**
83
+ * Submission attempted but couldn't complete — network failure, backend rejection, broken
84
+ * wallet provider, anything that isn't user-rejection. Carries the standard
85
+ * {@link FailurePayloadBase}.
86
+ */
87
+ type DepositSubmissionFailedEvent = StridgeEventBase<"deposit.submission.failed", "deposit", "flow", FailurePayloadBase>;
88
+ /**
89
+ * Background `fetchActiveSettlement` probe surfaced a pre-existing pending deposit on flow
90
+ * start — the user hadn't started this flow in this session but a prior unfinished deposit
91
+ * was detected and resumed. Payload is the settlement entity's pending snapshot.
92
+ *
93
+ * Withdraw has no symmetric event: the withdraw driver does not currently probe for
94
+ * pre-existing pending withdrawals (host-driven submission means the host already knows
95
+ * when a withdrawal was started). If withdraw later grows an equivalent probe, the
96
+ * symmetric `withdraw.settlement.resumed` will land at that time.
97
+ */
98
+ type DepositSettlementResumedEvent = StridgeEventBase<"deposit.settlement.resumed", "deposit", "flow", {
99
+ settlement: SettlementPendingPayload;
100
+ }>;
101
+ /**
102
+ * Settlement entity emitted a progressive pending update — confirmations advancing, partial
103
+ * fill credited, etc. Fires once per update; payload always reflects the current snapshot.
104
+ */
105
+ type DepositSettlementProgressedEvent = StridgeEventBase<"deposit.settlement.progressed", "deposit", "flow", {
106
+ settlement: SettlementPendingPayload;
107
+ }>;
108
+ /**
109
+ * Terminal success — settlement entity reached `ready{kind: "succeeded"}`. The flow is over;
110
+ * this event closes the session and the `flowId` is retired after it fires.
111
+ */
112
+ type DepositSettlementSucceededEvent = StridgeEventBase<"deposit.settlement.succeeded", "deposit", "flow", {
113
+ settlement: SettlementSuccessPayload;
114
+ }>;
115
+ /**
116
+ * Terminal failure — settlement entity reached `ready{kind: "failed"}` (driver-emitted
117
+ * classification) or the orchestrator escalated an FSM-level failure to the global error arm.
118
+ * Payload extends the standard {@link FailurePayloadBase} with settlement-specific fields.
119
+ */
120
+ type DepositSettlementFailedEvent = StridgeEventBase<"deposit.settlement.failed", "deposit", "flow", DepositSettlementFailurePayload>;
121
+ /**
122
+ * Flow ended before reaching a terminal state — typically the user closed the dialog
123
+ * mid-flow, or an AbortSignal fired. `payload.phase` indicates where in the lifecycle the
124
+ * cancellation happened so consumers can build drop-off funnels without parsing step names.
125
+ */
126
+ type DepositCancelledEvent = StridgeEventBase<"deposit.cancelled", "deposit", "flow", {
127
+ phase: DepositCancelPhase;
128
+ }>;
129
+ /** Union of every `deposit.*` `flow:*` event. */
130
+ type DepositFlowEvent = DepositQuoteRequestedEvent | DepositQuoteResolvedEvent | DepositQuoteFailedEvent | DepositQuoteExpiredEvent | DepositSubmissionBroadcastEvent | DepositSubmissionDeclinedEvent | DepositSubmissionFailedEvent | DepositSettlementResumedEvent | DepositSettlementProgressedEvent | DepositSettlementSucceededEvent | DepositSettlementFailedEvent | DepositCancelledEvent;
131
+ /**
132
+ * Dialog transitioned from `closed` to any open step. Mints the `flowId` (every subsequent
133
+ * event in this session carries the same `flowId`) and snapshots the `metadata` prop.
134
+ */
135
+ type DepositOpenedEvent = StridgeEventBase<"deposit.opened", "deposit", "ui", {
136
+ input: ResolvedOpenInput;
137
+ }>;
138
+ /**
139
+ * Dialog returned to `closed`. `payload.atStep` is the step name the dialog was on at close
140
+ * time. Fires after any terminal event (`*.succeeded` / `*.failed`) or `deposit.cancelled`
141
+ * in the same session.
142
+ */
143
+ type DepositClosedEvent = StridgeEventBase<"deposit.closed", "deposit", "ui", {
144
+ atStep: DepositStateName;
145
+ }>;
146
+ /**
147
+ * Dialog step transitioned. Fires on every logical step change including back-presses.
148
+ * `from === to` is not emitted; same-step `ctx` changes (e.g. `confirmDeposit` phase shifts)
149
+ * surface through their respective `flow:*` events instead.
150
+ */
151
+ type DepositStepChangedEvent = StridgeEventBase<"deposit.step.changed", "deposit", "ui", {
152
+ from: DepositStateName;
153
+ to: DepositStateName;
154
+ }>;
155
+ /**
156
+ * User clicked a deposit method tile (`wallet` / `transfer`) on the entry step. Fires on
157
+ * commit — picking is the action that advances the FSM.
158
+ */
159
+ type DepositMethodClickedEvent = StridgeEventBase<"deposit.method.clicked", "deposit", "ui", {
160
+ method: DepositMethod;
161
+ }>;
162
+ /**
163
+ * User clicked an asset row on the AssetPicker step. The asset is the driver-shaped balance row;
164
+ * use {@link BalanceItemPayload}'s `symbol` and `chainId` to identify it.
165
+ */
166
+ type DepositAssetClickedEvent = StridgeEventBase<"deposit.asset.clicked", "deposit", "ui", {
167
+ asset: BalanceItemPayload;
168
+ }>;
169
+ /**
170
+ * User typed in the amount field on the AmountEntry step. Fires per keystroke (no debounce);
171
+ * `payload.raw` is the literal input string, `payload.numeric` is the parsed value (or `null`
172
+ * when empty / unparseable). Use this for live UI; use {@link DepositAmountSubmittedEvent} for
173
+ * commitment.
174
+ */
175
+ type DepositAmountChangedEvent = StridgeEventBase<"deposit.amount.changed", "deposit", "ui", {
176
+ raw: string;
177
+ numeric: number | null;
178
+ }>;
179
+ /**
180
+ * User clicked the Max preset in the AmountEntry step (fills the amount with the full
181
+ * available balance). Mirrors {@link import("./withdraw").WithdrawMaxClickedEvent}.
182
+ */
183
+ type DepositMaxClickedEvent = StridgeEventBase<"deposit.max.clicked", "deposit", "ui", Record<string, never>>;
184
+ /**
185
+ * User submitted the AmountEntry step. `payload.amount` is the parsed numeric value (the FSM
186
+ * would not have advanced otherwise). The next event is typically `deposit.quote.requested`.
187
+ */
188
+ type DepositAmountSubmittedEvent = StridgeEventBase<"deposit.amount.submitted", "deposit", "ui", {
189
+ amount: number;
190
+ }>;
191
+ /**
192
+ * User clicked the Confirm button on the ConfirmDeposit step. Fires unconditionally on click —
193
+ * even when the button is disabled / mid-submit — so analytics can observe intent regardless
194
+ * of whether the click triggers FSM advance. Mirrors
195
+ * {@link import("./withdraw").WithdrawSubmitClickedEvent}. Use
196
+ * {@link DepositSubmissionConfirmedEvent} for the FSM-level "submission accepted" signal.
197
+ */
198
+ type DepositConfirmClickedEvent = StridgeEventBase<"deposit.confirm.clicked", "deposit", "ui", Record<string, never>>;
199
+ /**
200
+ * Confirm-step FSM transition to the submitting phase — the wallet prompt is about to fire.
201
+ * Fires only when the FSM accepts the submission (the click was valid); for the raw click
202
+ * signal (regardless of validity), subscribe to {@link DepositConfirmClickedEvent}. The
203
+ * next event is typically `deposit.submission.broadcast`, `deposit.submission.declined`, or
204
+ * `deposit.submission.failed`.
205
+ */
206
+ type DepositSubmissionConfirmedEvent = StridgeEventBase<"deposit.submission.confirmed", "deposit", "ui", Record<string, never>>;
207
+ /**
208
+ * User clicked the Back chevron in the dialog header on a non-root step. `payload.fromStep` is
209
+ * the step they were leaving. Withdraw has no symmetric event — the withdraw dialog is
210
+ * single-form with no Back affordance (the dialog X closes the flow instead).
211
+ */
212
+ type DepositBackClickedEvent = StridgeEventBase<"deposit.back.clicked", "deposit", "ui", {
213
+ fromStep: DepositStateName;
214
+ }>;
215
+ /**
216
+ * Inside the TransferCrypto compound, user picked a different source token. The selection
217
+ * affects which deposit address is shown but does not advance the FSM.
218
+ */
219
+ type DepositTransferTokenChangedEvent = StridgeEventBase<"deposit.transfer.token.changed", "deposit", "ui", {
220
+ token: TransferCryptoToken;
221
+ }>;
222
+ /** Inside the TransferCrypto compound, user picked a different source chain. */
223
+ type DepositTransferChainChangedEvent = StridgeEventBase<"deposit.transfer.chain.changed", "deposit", "ui", {
224
+ chain: TransferCryptoChain;
225
+ }>;
226
+ /** User clicked the copy-address button in the TransferCrypto compound. */
227
+ type DepositTransferAddressCopiedEvent = StridgeEventBase<"deposit.transfer.address.copied", "deposit", "ui", {
228
+ address: string;
229
+ }>;
230
+ /** Union of every `deposit.*` `ui:*` event. */
231
+ type DepositUiEvent = DepositOpenedEvent | DepositClosedEvent | DepositStepChangedEvent | DepositMethodClickedEvent | DepositAssetClickedEvent | DepositAmountChangedEvent | DepositMaxClickedEvent | DepositAmountSubmittedEvent | DepositConfirmClickedEvent | DepositSubmissionConfirmedEvent | DepositBackClickedEvent | DepositTransferTokenChangedEvent | DepositTransferChainChangedEvent | DepositTransferAddressCopiedEvent;
232
+ /** Union of every `deposit.*` event regardless of tier. */
233
+ type DepositEvent = DepositFlowEvent | DepositUiEvent;
234
+ //#endregion
235
+ export { DepositAmountChangedEvent, DepositAmountSubmittedEvent, DepositAssetClickedEvent, DepositBackClickedEvent, DepositCancelPhase, DepositCancelledEvent, DepositClosedEvent, DepositConfirmClickedEvent, DepositEvent, DepositFlowEvent, DepositMaxClickedEvent, DepositMethodClickedEvent, DepositOpenedEvent, DepositQuoteExpiredEvent, DepositQuoteFailedEvent, DepositQuoteRequestInput, DepositQuoteRequestedEvent, DepositQuoteResolvedEvent, DepositSettlementFailedEvent, DepositSettlementFailurePayload, DepositSettlementProgressedEvent, DepositSettlementResumedEvent, DepositSettlementSucceededEvent, DepositStepChangedEvent, DepositSubmissionBroadcastEvent, DepositSubmissionConfirmedEvent, DepositSubmissionDeclinedEvent, DepositSubmissionFailedEvent, DepositTransferAddressCopiedEvent, DepositTransferChainChangedEvent, DepositTransferTokenChangedEvent, DepositUiEvent };
@@ -0,0 +1,145 @@
1
+ //#region src/events/types/envelope.d.ts
2
+ /**
3
+ * Envelope, tier, flow, and failure types shared by every event variant in the unified bus.
4
+ *
5
+ * # Naming pattern (READ THIS BEFORE ADDING A NEW EVENT)
6
+ *
7
+ * Every event type is a string of the form `<flow>.<noun>.<verb-past>` (or
8
+ * `<flow>.<noun>.<sub-noun>.<verb-past>` for nested concepts):
9
+ *
10
+ * - `deposit.quote.resolved`
11
+ * - `withdraw.settlement.succeeded`
12
+ * - `deposit.transfer.address.copied`
13
+ * - `kit.support.opened`
14
+ *
15
+ * Rules:
16
+ *
17
+ * 1. **Lowercase, dot-segmented.** No camelCase, no colons, no slashes.
18
+ * 2. **Past-tense final verb.** Events describe things that already happened. `quote.resolved`,
19
+ * not `quote.resolve`. Even in-flight signals use past tense (`quote.requested` — the
20
+ * request *was made*).
21
+ * 3. **Same `noun.verb` across flows = same semantic concept.** A consumer who learns deposit
22
+ * events should immediately recognise the withdraw equivalents. If a concept exists in both
23
+ * flows, the trailing segments must match: `deposit.quote.resolved` ↔ `withdraw.quote.resolved`.
24
+ * 4. **Flow prefix is required.** Even for events that conceptually exist in both flows, each
25
+ * flow gets its own typed variant. The prefix lets TypeScript narrow payloads precisely on
26
+ * `e.type ===` checks without needing additional `e.flow ===` guards.
27
+ *
28
+ * # Tier rule
29
+ *
30
+ * - `tier: "flow"` — orchestrator/driver-emitted domain milestones (quote, submission,
31
+ * settlement). Fire whether or not the user sees any UI, as long as the orchestrator is
32
+ * running (which today means a dialog is mounted).
33
+ * - `tier: "ui"` — user-driven affordances and view-state changes from any kit-rendered
34
+ * element. Includes dialog lifecycle (open / close / step.changed) and widget interactions
35
+ * (keystrokes, selections, copy clicks). Fires only when the relevant kit-rendered component
36
+ * is mounted.
37
+ *
38
+ * # Envelope shape
39
+ *
40
+ * Every event variant ships as a `StridgeEventBase<...>`. Field discipline:
41
+ *
42
+ * - `type` — unique string discriminator. Stable across versions; never reshape an existing
43
+ * `type`. Adding a new event = adding a new variant to the appropriate union.
44
+ * - `flow` — duplicated from the `type` prefix for cheap field-based filtering by analytics
45
+ * integrations that don't want to string-parse.
46
+ * - `tier` — duplicated from per-variant convention for filterable inspection.
47
+ * - `timestamp` — `Date.now()` at emit; wall-clock, not `performance.now()`, because
48
+ * consumers want it for logging/funnels.
49
+ * - `flowId` — session correlation id. Minted at `<flow>.opened`, retired after the terminal
50
+ * event (`*.settlement.succeeded` / `*.settlement.failed` / `*.cancelled`). Always
51
+ * `string` for `flow:*` and `ui:*` events; `null` for `kit:*` events (which have no flow
52
+ * context to belong to).
53
+ * - `payload` — event-specific data, always an object even when single-field, so future
54
+ * fields can be added non-breakingly.
55
+ * - `metadata` — consumer-attached, snapshotted at `<flow>.opened` and frozen for the
56
+ * session. Always present (empty object if the consumer didn't supply any). `Record<string,
57
+ * unknown>` — the kit does not validate, normalise, or enforce a schema.
58
+ *
59
+ * # What's intentionally NOT in the envelope
60
+ *
61
+ * - No `id` per-event uuid — `flowId + type + timestamp` is sufficient correlation.
62
+ * - No `preventDefault` / `stopPropagation` — events are read-only notifications.
63
+ * - No `version` field — versioning happens through the union, not at runtime.
64
+ * - No `source: "user" | "system"` distinction beyond `tier` — adding finer grain invites
65
+ * bikeshed without paying for itself.
66
+ */
67
+ /** Flow identifier — one per orchestrator family, plus `"kit"` for flow-less provider events. */
68
+ type StridgeEventFlow = "deposit" | "withdraw" | "kit";
69
+ /** Delivery tier — see envelope JSDoc for the rule. */
70
+ type StridgeEventTier = "flow" | "ui";
71
+ /**
72
+ * Generic envelope every event variant extends. Concrete variants narrow the four type
73
+ * parameters so `e.type === "..."` discrimination narrows `flow`, `tier`, and `payload`
74
+ * in lockstep.
75
+ */
76
+ interface StridgeEventBase<TType extends string, TFlow extends StridgeEventFlow, TTier extends StridgeEventTier, TPayload> {
77
+ /** Stable string discriminator. See the naming pattern in this file's top-of-file JSDoc. */
78
+ type: TType;
79
+ /** Originating flow. Always derivable from the `type` prefix; duplicated for cheap field-based filtering. */
80
+ flow: TFlow;
81
+ /** Delivery tier. */
82
+ tier: TTier;
83
+ /** Wall-clock millisecond timestamp at emit. */
84
+ timestamp: number;
85
+ /**
86
+ * Session correlation id. `string` for flow-scoped events, `null` for `kit:*` events
87
+ * (which have no flow context to belong to).
88
+ */
89
+ flowId: TFlow extends "kit" ? null : string;
90
+ /** Event-specific payload. Always an object even when single-field. */
91
+ payload: TPayload;
92
+ /**
93
+ * Consumer-attached metadata, snapshotted at `<flow>.opened`, frozen for the session.
94
+ * Empty object when the consumer didn't supply any. Consumer-typed at the consumption
95
+ * site — the kit does not validate or normalise.
96
+ */
97
+ metadata: Record<string, unknown>;
98
+ }
99
+ /**
100
+ * Stable taxonomy of failure codes carried by every `*.failed` event. Constrained enum (not
101
+ * free string) because consumers writing `switch(code)` need exhaustiveness and analytics
102
+ * platforms need bounded cardinality.
103
+ *
104
+ * Every internal failure path must map to one of these. Add new codes here when a new
105
+ * failure category genuinely appears — don't widen the union with overlapping codes.
106
+ */
107
+ type FailureCode = /** Transport-level fetch failure, DNS error, browser offline. */"network" /** Operation exceeded its deadline before producing a result. */ | "timeout" /** Backend returned 429 / equivalent rate-limit signal. */ | "rate_limited" /** Gateway key invalid, scope mismatch, or session expired. */ | "unauthorized" /** Requested amount exceeds available balance. */ | "insufficient_funds" /** Backend rejected the payload as malformed (validation failure). */ | "invalid_input" /** Quote went stale between request and submit. */ | "quote_expired" /** On-chain transaction reverted. */ | "tx_reverted" /** Transaction replaced or dropped from the mempool before inclusion. */ | "tx_dropped" /** Backend couldn't correlate a settlement to the submitted transaction. */ | "settlement_lost" /** Catch-all for anything else; consumers should treat as opaque. */ | "internal";
108
+ /**
109
+ * Shape carried by every `*.failed` event in the bus. Common base lets generic error handlers
110
+ * write `analytics.track("error", e.payload.code, e.payload.reason)` once and have it work
111
+ * across every flow and every failure point.
112
+ *
113
+ * Per-event extensions (e.g. `SettlementFailurePayload`) extend this with richer fields when
114
+ * the failure has additional structure worth surfacing.
115
+ *
116
+ * **`.declined` (user refused a wallet prompt) and `.cancelled` (flow interrupted by close /
117
+ * AbortSignal) are NOT `.failed`** — they have their own event names with their own (often
118
+ * empty) payloads. Conflating them would let analytics count user choices as errors.
119
+ */
120
+ interface FailurePayloadBase {
121
+ /**
122
+ * Stable taxonomy code. Drives consumer logic: retry decisions, custom messaging,
123
+ * error-grouping in analytics dashboards.
124
+ */
125
+ code: FailureCode;
126
+ /**
127
+ * Human-readable reason, already localised by the kit. Safe to render directly to users.
128
+ * Consumers who want raw keys for their own messaging branch on {@link code} instead.
129
+ */
130
+ reason: string;
131
+ /**
132
+ * Whether retrying the same operation could plausibly succeed. `true` for transient
133
+ * failures (`network`, `timeout`, `rate_limited`); `false` for permanent ones
134
+ * (`unauthorized`, `invalid_input`, `tx_reverted`).
135
+ */
136
+ retryable: boolean;
137
+ /**
138
+ * Raw cause for debugging only — typically the underlying `Error`, fetch `Response`, or
139
+ * wallet-provider error object. Never displayed; safe to log. Consumers must not depend
140
+ * on its shape.
141
+ */
142
+ cause?: unknown;
143
+ }
144
+ //#endregion
145
+ export { FailureCode, FailurePayloadBase, StridgeEventBase, StridgeEventFlow, StridgeEventTier };
@@ -0,0 +1,31 @@
1
+ import { FailureCode, FailurePayloadBase, StridgeEventBase, StridgeEventFlow, StridgeEventTier } from "./envelope.js";
2
+ import { DepositAmountChangedEvent, DepositAmountSubmittedEvent, DepositAssetClickedEvent, DepositBackClickedEvent, DepositCancelPhase, DepositCancelledEvent, DepositClosedEvent, DepositConfirmClickedEvent, DepositEvent, DepositFlowEvent, DepositMaxClickedEvent, DepositMethodClickedEvent, DepositOpenedEvent, DepositQuoteExpiredEvent, DepositQuoteFailedEvent, DepositQuoteRequestInput, DepositQuoteRequestedEvent, DepositQuoteResolvedEvent, DepositSettlementFailedEvent, DepositSettlementFailurePayload, DepositSettlementProgressedEvent, DepositSettlementResumedEvent, DepositSettlementSucceededEvent, DepositStepChangedEvent, DepositSubmissionBroadcastEvent, DepositSubmissionConfirmedEvent, DepositSubmissionDeclinedEvent, DepositSubmissionFailedEvent, DepositTransferAddressCopiedEvent, DepositTransferChainChangedEvent, DepositTransferTokenChangedEvent, DepositUiEvent } from "./deposit.js";
3
+ import { KitEvent, KitSupportClickedEvent, KitTermsClickedEvent } from "./kit.js";
4
+ import { WithdrawAmountChangedEvent, WithdrawBreakdownClickedEvent, WithdrawCancelPhase, WithdrawCancelledEvent, WithdrawClosedEvent, WithdrawEvent, WithdrawFlowEvent, WithdrawMaxClickedEvent, WithdrawOpenedEvent, WithdrawQuoteExpiredEvent, WithdrawQuoteFailedEvent, WithdrawQuoteRequestedEvent, WithdrawQuoteResolvedEvent, WithdrawReceiveChainChangedEvent, WithdrawReceiveTokenChangedEvent, WithdrawRecipientChangedEvent, WithdrawSettlementFailedEvent, WithdrawSettlementFailurePayload, WithdrawSettlementProgressedEvent, WithdrawSettlementSucceededEvent, WithdrawStepChangedEvent, WithdrawSubmissionBroadcastEvent, WithdrawSubmissionConfirmedEvent, WithdrawSubmissionDeclinedEvent, WithdrawSubmissionFailedEvent, WithdrawSubmitClickedEvent, WithdrawUiEvent } from "./withdraw.js";
5
+
6
+ //#region src/events/types/index.d.ts
7
+ /**
8
+ * Every `flow:*` event across all flows. Headless-safe — this is what
9
+ * `useStridgeFlowEvents` narrows its handler to. Does not include any `ui:*` or `kit:*`
10
+ * events; consumers who only render the dialog (no widgets, no provider affordances) can
11
+ * subscribe to this union and never see a UI-noise event in their autocomplete.
12
+ */
13
+ type FlowEvent = DepositFlowEvent | WithdrawFlowEvent;
14
+ /**
15
+ * Every `ui:*` event across all flows, plus every `kit:*` provider-scoped event (kit
16
+ * affordances are user-driven, so they share the `ui` tier today even though they don't
17
+ * belong to a deposit/withdraw flow). Does NOT include `flow:*` events — for the firehose
18
+ * union, use {@link StridgeEvent}.
19
+ */
20
+ type UiEvent = DepositUiEvent | WithdrawUiEvent | KitEvent;
21
+ /**
22
+ * Firehose union — every event the kit ever emits. Equivalent to `FlowEvent | UiEvent`.
23
+ * What `useStridgeEvents` hands to its handler.
24
+ */
25
+ type StridgeEvent = FlowEvent | UiEvent;
26
+ /** Convenience: every distinct `type` literal across the full union. */
27
+ type StridgeEventType = StridgeEvent["type"];
28
+ type FlowEventType = FlowEvent["type"];
29
+ type UiEventType = UiEvent["type"];
30
+ //#endregion
31
+ export { FlowEvent, FlowEventType, StridgeEvent, StridgeEventType, UiEvent, UiEventType };
@@ -0,0 +1,23 @@
1
+ import { SupportOpenContext } from "../../shared/support/types.js";
2
+ import { TermsSelectContext } from "../../shared/terms/types.js";
3
+ import { StridgeEventBase } from "./envelope.js";
4
+ //#region src/events/types/kit.d.ts
5
+ /**
6
+ * User clicked the support entry point (the "Get help" link / button). Fires regardless of
7
+ * whether the consumer provided a custom `support.onOpen` handler — the bus event is an
8
+ * observation channel for analytics, the prop is a behaviour-override contract. Both coexist.
9
+ */
10
+ type KitSupportClickedEvent = StridgeEventBase<"kit.support.clicked", "kit", "ui", {
11
+ context: SupportOpenContext;
12
+ }>;
13
+ /**
14
+ * User clicked a terms link. Fires regardless of whether the consumer provided a custom
15
+ * `terms.onSelect` handler.
16
+ */
17
+ type KitTermsClickedEvent = StridgeEventBase<"kit.terms.clicked", "kit", "ui", {
18
+ context: TermsSelectContext;
19
+ }>;
20
+ /** Union of every `kit.*` event. */
21
+ type KitEvent = KitSupportClickedEvent | KitTermsClickedEvent;
22
+ //#endregion
23
+ export { KitEvent, KitSupportClickedEvent, KitTermsClickedEvent };