@venlyfinance/react 0.4.0 → 0.5.0
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.
- package/AGENTS.md +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/keys.d.ts +4 -0
- package/dist/keys.js +1 -0
- package/dist/queries.d.ts +32 -10
- package/dist/queries.js +30 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -9,6 +9,7 @@ You are building a financial product UI on `@venlyfinance/react`. These rules ex
|
|
|
9
9
|
3. **Never place `clientSecret` in browser code.** The provider throws if you try. For browser apps use `proxyClientOptions()` against your own backend route.
|
|
10
10
|
4. **Money movement is stage-then-confirm.** Render a review step showing `state.staged` (the exact request) before calling `confirm()`. Never wire a form submit directly to execution.
|
|
11
11
|
5. **Approval UIs render the rule, not the error.** Use `capability` from `useFourEyesApproval`: when `reason` is `"actor-is-creator"`, say that a second person must approve – do not show buttons that will be refused. On failure `"stale-version"`, refetch and let the operator re-decide; never auto-retry an approval.
|
|
12
|
+
6. **Gate both the screen and its runtime contract, and wire both into CI.** Run `npx @venlyfinance/settlement-mcp review "src/**/*.tsx"` for the design contract and `npx @venlyfinance/settlement-mcp verify "src/**/*.{ts,tsx}"` for package/provider/hook/proxy composition. Each fails (exit 1) on any error-severity finding. A deliberate, justified exception carries `venly-allow:<rule-id>` on the offending line or the line above.
|
|
12
13
|
|
|
13
14
|
## Rendering money states
|
|
14
15
|
|
|
@@ -31,4 +32,4 @@ The UI kit's auth and team blocks therefore render against two adapter interface
|
|
|
31
32
|
## Demo choreography (mock mode)
|
|
32
33
|
|
|
33
34
|
`useVenlyMock()` exposes the store controls. A credible end-to-end demo:
|
|
34
|
-
create party → `advanceVerification(id)` → create account → virtual bank account (note its `referenceCode`) → stage + confirm a transfer → `advanceTransfer(id)` → show the ledger. Inject failures with `failNext("CONFLICT")` to show the stale-version approval path – error states are part of the product.
|
|
35
|
+
create party → `advanceVerification(id)` → create account → virtual bank account (note its `referenceCode`) → **fund it: `simulations.inbound.credit(vbaId, 500)`** (a new account holds nothing, as in production; an unfunded transfer is refused with `402 insufficient-funds`) → stage + confirm a transfer → `advanceTransfer(id)` → show the ledger, and `simulations.ledger.verify()` to prove it balances. Inject failures with `failNext("CONFLICT")` to show the stale-version approval path – error states are part of the product.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { VenlyProvider, useVenly, useVenlyMock, type VenlyClients, type VenlyProviderProps, type VenlyReactEnvironment, } from "./provider.js";
|
|
2
2
|
export { venlyKeys } from "./keys.js";
|
|
3
3
|
export { venlyQueries, type AccountsQuery, type FeeQuoteInput, type PartiesQuery, type RampRequestsQuery, type TransfersQuery, type VirtualBankAccountsQuery, type WalletsQuery, } from "./query-options.js";
|
|
4
|
-
export { useAccount, useAccounts, useCompanyFees, useFeeQuote, useParties, useParty, useRampRequest, useRampRequests, useReferenceData, useTransfer, useTransfers, useVirtualBankAccounts, useWallets, useCompanyBankAccount, useCompanyBankAccounts, useCompanyWallets, useBankAccountConfig, useDepositWallets, useRampPairs, useSupportedAssets, useAccountSupportedAssets, } from "./queries.js";
|
|
4
|
+
export { useAccount, useAccounts, useCompanyFees, useFeeQuote, useParties, useParty, useRampRequest, useRampRequests, useReferenceData, useTransfer, useTransfers, useTransfersForPeriod, collectTransfersForPeriod, type TransferPeriod, type TransfersForPeriodPage, useVirtualBankAccounts, useWallets, useCompanyBankAccount, useCompanyBankAccounts, useCompanyWallets, useBankAccountConfig, useDepositWallets, useRampPairs, useSupportedAssets, useAccountSupportedAssets, } from "./queries.js";
|
|
5
5
|
export { useCreateAccount, useCreateParty, useCreatePaymentSession, useCreateRampRequest, useCreateVirtualBankAccount, useCreateCompanyBankAccount, useCreateCompanyWallet, useSetRampAmount, useInitiateRamp, } from "./mutations.js";
|
|
6
6
|
export { StagedTransferController, useStagedTransfer, validateDraft, type StagedRequest, type StagedTransferOptions, type StagedTransferState, type TransferDraft, } from "./flows/staged-transfer.js";
|
|
7
7
|
export { approvalCapabilities, interpretApprovalError, useFourEyesApproval, type ApprovalCapability, type ApprovalFailureKind, type FourEyesState, } from "./flows/four-eyes.js";
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ export { VenlyProvider, useVenly, useVenlyMock, } from "./provider.js";
|
|
|
4
4
|
export { venlyKeys } from "./keys.js";
|
|
5
5
|
export { venlyQueries, } from "./query-options.js";
|
|
6
6
|
// Read hooks
|
|
7
|
-
export { useAccount, useAccounts, useCompanyFees, useFeeQuote, useParties, useParty, useRampRequest, useRampRequests, useReferenceData, useTransfer, useTransfers, useVirtualBankAccounts, useWallets, useCompanyBankAccount, useCompanyBankAccounts, useCompanyWallets, useBankAccountConfig, useDepositWallets, useRampPairs, useSupportedAssets, useAccountSupportedAssets, } from "./queries.js";
|
|
7
|
+
export { useAccount, useAccounts, useCompanyFees, useFeeQuote, useParties, useParty, useRampRequest, useRampRequests, useReferenceData, useTransfer, useTransfers, useTransfersForPeriod, collectTransfersForPeriod, useVirtualBankAccounts, useWallets, useCompanyBankAccount, useCompanyBankAccounts, useCompanyWallets, useBankAccountConfig, useDepositWallets, useRampPairs, useSupportedAssets, useAccountSupportedAssets, } from "./queries.js";
|
|
8
8
|
// Write hooks
|
|
9
9
|
export { useCreateAccount, useCreateParty, useCreatePaymentSession, useCreateRampRequest, useCreateVirtualBankAccount, useCreateCompanyBankAccount, useCreateCompanyWallet, useSetRampAmount, useInitiateRamp, } from "./mutations.js";
|
|
10
10
|
// Flow machines: the regulated-money lifecycles
|
package/dist/keys.d.ts
CHANGED
|
@@ -13,6 +13,10 @@ export declare const venlyKeys: {
|
|
|
13
13
|
readonly accountSupportedAssets: (accountId: string) => readonly ["venly", "account", string, "supported-assets"];
|
|
14
14
|
readonly virtualBankAccounts: (accountId: string, query?: unknown) => readonly ["venly", "account", string, "virtual-bank-accounts", {} | null];
|
|
15
15
|
readonly transfers: (accountId: string, query?: unknown) => readonly ["venly", "account", string, "transfers", {} | null];
|
|
16
|
+
readonly transfersForPeriod: (accountId: string, period: {
|
|
17
|
+
start: string;
|
|
18
|
+
end: string;
|
|
19
|
+
}) => readonly ["venly", "account", string, "transfers-for-period", string, string];
|
|
16
20
|
readonly transfer: (accountId: string, transferId: string) => readonly ["venly", "account", string, "transfer", string];
|
|
17
21
|
readonly rampRequests: (query?: unknown) => readonly ["venly", "ramp-requests", {} | null];
|
|
18
22
|
readonly rampRequest: (id: string) => readonly ["venly", "ramp-request", string];
|
package/dist/keys.js
CHANGED
|
@@ -13,6 +13,7 @@ export const venlyKeys = {
|
|
|
13
13
|
accountSupportedAssets: (accountId) => ["venly", "account", accountId, "supported-assets"],
|
|
14
14
|
virtualBankAccounts: (accountId, query) => ["venly", "account", accountId, "virtual-bank-accounts", query ?? null],
|
|
15
15
|
transfers: (accountId, query) => ["venly", "account", accountId, "transfers", query ?? null],
|
|
16
|
+
transfersForPeriod: (accountId, period) => ["venly", "account", accountId, "transfers-for-period", period.start, period.end],
|
|
16
17
|
transfer: (accountId, transferId) => ["venly", "account", accountId, "transfer", transferId],
|
|
17
18
|
rampRequests: (query) => ["venly", "ramp-requests", query ?? null],
|
|
18
19
|
rampRequest: (id) => ["venly", "ramp-request", id],
|
package/dist/queries.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type UseQueryOptions } from "@tanstack/react-query";
|
|
2
|
+
import { type Page, type Transfer as TransferRow } from "@venlyfinance/sdk";
|
|
2
3
|
import { venlyQueries, type AccountsQuery, type FeeQuoteInput, type PartiesQuery, type RampRequestsQuery, type TransfersQuery, type VirtualBankAccountsQuery, type WalletsQuery, type CompanyBankAccountsQuery, type CompanyWalletsQuery, type DepositWalletsQuery } from "./query-options.js";
|
|
3
4
|
type Tune<T> = Omit<UseQueryOptions<T, Error>, "queryKey" | "queryFn">;
|
|
4
|
-
export declare function useParties(query?: PartiesQuery, options?: Tune<PartiesPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<
|
|
5
|
+
export declare function useParties(query?: PartiesQuery, options?: Tune<PartiesPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<Page<{
|
|
5
6
|
id?: string;
|
|
6
7
|
externalId?: string;
|
|
7
8
|
partyType?: "INDIVIDUAL" | "ORGANISATION";
|
|
@@ -35,7 +36,7 @@ export declare function useParty(partyId: string | undefined, options?: Tune<Par
|
|
|
35
36
|
version?: number;
|
|
36
37
|
}>, Error>;
|
|
37
38
|
type Party = Awaited<ReturnType<ReturnType<typeof venlyQueries.party>["queryFn"]>>;
|
|
38
|
-
export declare function useAccounts(query?: AccountsQuery, options?: Tune<AccountsPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<
|
|
39
|
+
export declare function useAccounts(query?: AccountsQuery, options?: Tune<AccountsPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<Page<{
|
|
39
40
|
id?: string;
|
|
40
41
|
externalId?: string;
|
|
41
42
|
name?: string;
|
|
@@ -55,7 +56,7 @@ export declare function useAccount(accountId: string | undefined, options?: Tune
|
|
|
55
56
|
version?: number;
|
|
56
57
|
}>, Error>;
|
|
57
58
|
type Account = Awaited<ReturnType<ReturnType<typeof venlyQueries.account>["queryFn"]>>;
|
|
58
|
-
export declare function useWallets(accountId: string | undefined, query?: WalletsQuery, options?: Tune<WalletsPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<
|
|
59
|
+
export declare function useWallets(accountId: string | undefined, query?: WalletsQuery, options?: Tune<WalletsPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<Page<{
|
|
59
60
|
asset?: string;
|
|
60
61
|
contractAddress?: string;
|
|
61
62
|
amount?: import("@venlyfinance/sdk").FinanceComponents["schemas"]["CryptoBalanceSummaryDto"];
|
|
@@ -65,7 +66,7 @@ type WalletsPage = Awaited<ReturnType<ReturnType<typeof venlyQueries.wallets>["q
|
|
|
65
66
|
* Tenant-wide supported assets. `decimals` per asset is the render contract
|
|
66
67
|
* for amounts; cached hard (the asset set changes on deploys, not minutes).
|
|
67
68
|
*/
|
|
68
|
-
export declare function useSupportedAssets(options?: Tune<SupportedAssetsPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<
|
|
69
|
+
export declare function useSupportedAssets(options?: Tune<SupportedAssetsPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<Page<{
|
|
69
70
|
chain?: "AVALANCHE" | "BASE" | "ETHEREUM" | "POLYGON" | "SOLANA";
|
|
70
71
|
cryptoCurrency?: string;
|
|
71
72
|
decimals?: number;
|
|
@@ -76,7 +77,7 @@ type SupportedAssetsPage = Awaited<ReturnType<ReturnType<typeof venlyQueries.sup
|
|
|
76
77
|
* Account-scoped supported assets (adds `permitStatus`). Not frozen:
|
|
77
78
|
* permit status moves while an asset activates.
|
|
78
79
|
*/
|
|
79
|
-
export declare function useAccountSupportedAssets(accountId: string | undefined, options?: Tune<AccountSupportedAssetsPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<
|
|
80
|
+
export declare function useAccountSupportedAssets(accountId: string | undefined, options?: Tune<AccountSupportedAssetsPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<Page<{
|
|
80
81
|
chain?: "AVALANCHE" | "BASE" | "ETHEREUM" | "POLYGON" | "SOLANA";
|
|
81
82
|
cryptoCurrency?: string;
|
|
82
83
|
decimals?: number;
|
|
@@ -84,7 +85,7 @@ export declare function useAccountSupportedAssets(accountId: string | undefined,
|
|
|
84
85
|
permitStatus?: "READY" | "ACTIVATING" | "ACTION_REQUIRED" | "PENDING" | "FAILED" | "NO_WALLET";
|
|
85
86
|
}>>, Error>;
|
|
86
87
|
type AccountSupportedAssetsPage = Awaited<ReturnType<ReturnType<typeof venlyQueries.accountSupportedAssets>["queryFn"]>>;
|
|
87
|
-
export declare function useVirtualBankAccounts(accountId: string | undefined, query?: VirtualBankAccountsQuery, options?: Tune<VibaPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<
|
|
88
|
+
export declare function useVirtualBankAccounts(accountId: string | undefined, query?: VirtualBankAccountsQuery, options?: Tune<VibaPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<Page<{
|
|
88
89
|
id?: string;
|
|
89
90
|
accountId?: string;
|
|
90
91
|
bankAccountType?: "EUR_SEPA" | "USD_ACH";
|
|
@@ -104,7 +105,7 @@ export declare function useVirtualBankAccounts(accountId: string | undefined, qu
|
|
|
104
105
|
updatedAt?: string;
|
|
105
106
|
}>>, Error>;
|
|
106
107
|
type VibaPage = Awaited<ReturnType<ReturnType<typeof venlyQueries.virtualBankAccounts>["queryFn"]>>;
|
|
107
|
-
export declare function useTransfers(accountId: string | undefined, query?: TransfersQuery, options?: Tune<TransfersPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<
|
|
108
|
+
export declare function useTransfers(accountId: string | undefined, query?: TransfersQuery, options?: Tune<TransfersPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<Page<{
|
|
108
109
|
id?: string;
|
|
109
110
|
senderAccountId?: string;
|
|
110
111
|
receiverAccountId?: string;
|
|
@@ -122,6 +123,27 @@ export declare function useTransfers(accountId: string | undefined, query?: Tran
|
|
|
122
123
|
updatedAt?: string;
|
|
123
124
|
}>>, Error>;
|
|
124
125
|
type TransfersPage = Awaited<ReturnType<ReturnType<typeof venlyQueries.transfers>["queryFn"]>>;
|
|
126
|
+
export type TransferPeriod = {
|
|
127
|
+
start: string;
|
|
128
|
+
end: string;
|
|
129
|
+
};
|
|
130
|
+
export type TransfersForPeriodPage = {
|
|
131
|
+
/** Rows whose `createdAt` falls in `[start, end]`. */
|
|
132
|
+
items: TransferRow[];
|
|
133
|
+
/**
|
|
134
|
+
* Every transfer on the account after paging to completion. Opening and
|
|
135
|
+
* closing walk from the current wallet total through this full ledger;
|
|
136
|
+
* a window-only set would silently drop later movements.
|
|
137
|
+
*/
|
|
138
|
+
ledger: TransferRow[];
|
|
139
|
+
resultPresent: boolean;
|
|
140
|
+
};
|
|
141
|
+
/**
|
|
142
|
+
* Page every transfer on the account (the list contract has no date filter),
|
|
143
|
+
* then keep the window. `iteratePages` walks `hasNextPage`.
|
|
144
|
+
*/
|
|
145
|
+
export declare function collectTransfersForPeriod(list: (query?: TransfersQuery) => Promise<Page<Transfer>>, period: TransferPeriod, pageSize?: number): Promise<TransfersForPeriodPage>;
|
|
146
|
+
export declare function useTransfersForPeriod(accountId: string | undefined, period: TransferPeriod | undefined, options?: Tune<TransfersForPeriodPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<TransfersForPeriodPage>, Error>;
|
|
125
147
|
export declare function useTransfer(accountId: string | undefined, transferId: string | undefined, options?: Tune<Transfer>): import("@tanstack/react-query").UseQueryResult<NoInfer<{
|
|
126
148
|
id?: string;
|
|
127
149
|
senderAccountId?: string;
|
|
@@ -140,7 +162,7 @@ export declare function useTransfer(accountId: string | undefined, transferId: s
|
|
|
140
162
|
updatedAt?: string;
|
|
141
163
|
}>, Error>;
|
|
142
164
|
type Transfer = Awaited<ReturnType<ReturnType<typeof venlyQueries.transfer>["queryFn"]>>;
|
|
143
|
-
export declare function useRampRequests(query?: RampRequestsQuery, options?: Tune<RampPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<
|
|
165
|
+
export declare function useRampRequests(query?: RampRequestsQuery, options?: Tune<RampPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<Page<{
|
|
144
166
|
id?: string;
|
|
145
167
|
paymentReference?: string;
|
|
146
168
|
rampType?: "ON_RAMP" | "OFF_RAMP";
|
|
@@ -220,7 +242,7 @@ export declare function useFeeQuote(input: FeeQuoteInput | undefined, options?:
|
|
|
220
242
|
percentage?: number;
|
|
221
243
|
}>, Error>;
|
|
222
244
|
type FeeQuote = Awaited<ReturnType<ReturnType<typeof venlyQueries.feeQuote>["queryFn"]>>;
|
|
223
|
-
export declare function useCompanyBankAccounts(query?: CompanyBankAccountsQuery, options?: Tune<BankAccountsPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<
|
|
245
|
+
export declare function useCompanyBankAccounts(query?: CompanyBankAccountsQuery, options?: Tune<BankAccountsPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<Page<{
|
|
224
246
|
id?: string;
|
|
225
247
|
name?: string;
|
|
226
248
|
bankName?: string;
|
|
@@ -268,7 +290,7 @@ export declare function useCompanyBankAccount(id: string | undefined, options?:
|
|
|
268
290
|
currency?: string;
|
|
269
291
|
}>, Error>;
|
|
270
292
|
type BankAccountDetail = Awaited<ReturnType<ReturnType<typeof venlyQueries.companyBankAccount>["queryFn"]>>;
|
|
271
|
-
export declare function useCompanyWallets(query?: CompanyWalletsQuery, options?: Tune<WalletsListPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<
|
|
293
|
+
export declare function useCompanyWallets(query?: CompanyWalletsQuery, options?: Tune<WalletsListPage>): import("@tanstack/react-query").UseQueryResult<NoInfer<Page<{
|
|
272
294
|
id?: string;
|
|
273
295
|
description?: string;
|
|
274
296
|
address?: string;
|
package/dist/queries.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { useQuery } from "@tanstack/react-query";
|
|
2
|
+
import { iteratePages } from "@venlyfinance/sdk";
|
|
2
3
|
import { useVenly } from "./provider.js";
|
|
3
4
|
import { venlyQueries, } from "./query-options.js";
|
|
5
|
+
import { venlyKeys } from "./keys.js";
|
|
4
6
|
export function useParties(query, options) {
|
|
5
7
|
const clients = useVenly();
|
|
6
8
|
return useQuery({ ...venlyQueries.parties(clients, query), ...options });
|
|
@@ -73,6 +75,34 @@ export function useTransfers(accountId, query, options) {
|
|
|
73
75
|
...options,
|
|
74
76
|
});
|
|
75
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Page every transfer on the account (the list contract has no date filter),
|
|
80
|
+
* then keep the window. `iteratePages` walks `hasNextPage`.
|
|
81
|
+
*/
|
|
82
|
+
export async function collectTransfersForPeriod(list, period, pageSize = 20) {
|
|
83
|
+
const ledger = [];
|
|
84
|
+
for await (const item of iteratePages((params) => list({ page: params.page, size: params.size }), {
|
|
85
|
+
size: pageSize,
|
|
86
|
+
})) {
|
|
87
|
+
ledger.push(item);
|
|
88
|
+
}
|
|
89
|
+
const items = ledger.filter((transfer) => {
|
|
90
|
+
const at = transfer.createdAt;
|
|
91
|
+
return Boolean(at && at >= period.start && at <= period.end);
|
|
92
|
+
});
|
|
93
|
+
return { items, ledger, resultPresent: true };
|
|
94
|
+
}
|
|
95
|
+
export function useTransfersForPeriod(accountId, period, options) {
|
|
96
|
+
const clients = useVenly();
|
|
97
|
+
const start = period?.start ?? "";
|
|
98
|
+
const end = period?.end ?? "";
|
|
99
|
+
return useQuery({
|
|
100
|
+
queryKey: venlyKeys.transfersForPeriod(accountId ?? "", { start, end }),
|
|
101
|
+
queryFn: () => collectTransfersForPeriod((query) => clients.finance.transfers.list(accountId ?? "", query), { start, end }),
|
|
102
|
+
enabled: Boolean(accountId && start && end) && (options?.enabled ?? true),
|
|
103
|
+
...options,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
76
106
|
export function useTransfer(accountId, transferId, options) {
|
|
77
107
|
const clients = useVenly();
|
|
78
108
|
return useQuery({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@venlyfinance/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Headless React layer for the Venly Finance and Fundflow APIs: provider, TanStack Query hooks, and flow state machines for regulated money movement. Runs with zero credentials in mock mode.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|