@v3finance/core-sdk 0.1.0 → 0.2.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/CHANGELOG.md +397 -7
- package/README.md +215 -72
- package/dist/cjs/client.d.ts +67 -22
- package/dist/cjs/client.d.ts.map +1 -1
- package/dist/cjs/client.js +38 -2
- package/dist/cjs/client.js.map +1 -1
- package/dist/cjs/core/errors.d.ts +30 -10
- package/dist/cjs/core/errors.d.ts.map +1 -1
- package/dist/cjs/core/errors.js +47 -15
- package/dist/cjs/core/errors.js.map +1 -1
- package/dist/cjs/core/gated.d.ts +21 -3
- package/dist/cjs/core/gated.d.ts.map +1 -1
- package/dist/cjs/core/gated.js +12 -3
- package/dist/cjs/core/gated.js.map +1 -1
- package/dist/cjs/core/http.d.ts +12 -8
- package/dist/cjs/core/http.d.ts.map +1 -1
- package/dist/cjs/core/http.js +130 -40
- package/dist/cjs/core/http.js.map +1 -1
- package/dist/cjs/core/pagination.d.ts +28 -1
- package/dist/cjs/core/pagination.d.ts.map +1 -1
- package/dist/cjs/core/pagination.js +36 -1
- package/dist/cjs/core/pagination.js.map +1 -1
- package/dist/cjs/generated/operations.js +1 -1
- package/dist/cjs/generated/types.d.ts +948 -172
- package/dist/cjs/generated/types.d.ts.map +1 -1
- package/dist/cjs/index.d.ts +32 -8
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +12 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/resources/addresses.d.ts +22 -8
- package/dist/cjs/resources/addresses.d.ts.map +1 -1
- package/dist/cjs/resources/addresses.js +7 -1
- package/dist/cjs/resources/addresses.js.map +1 -1
- package/dist/cjs/resources/admin.d.ts +150 -25
- package/dist/cjs/resources/admin.d.ts.map +1 -1
- package/dist/cjs/resources/admin.js +94 -23
- package/dist/cjs/resources/admin.js.map +1 -1
- package/dist/cjs/resources/approvals.d.ts +46 -5
- package/dist/cjs/resources/approvals.d.ts.map +1 -1
- package/dist/cjs/resources/approvals.js +27 -4
- package/dist/cjs/resources/approvals.js.map +1 -1
- package/dist/cjs/resources/balances.d.ts +152 -16
- package/dist/cjs/resources/balances.d.ts.map +1 -1
- package/dist/cjs/resources/balances.js +9 -5
- package/dist/cjs/resources/balances.js.map +1 -1
- package/dist/cjs/resources/categories.d.ts +93 -21
- package/dist/cjs/resources/categories.d.ts.map +1 -1
- package/dist/cjs/resources/categories.js +65 -18
- package/dist/cjs/resources/categories.js.map +1 -1
- package/dist/cjs/resources/counterparties.d.ts +26 -3
- package/dist/cjs/resources/counterparties.d.ts.map +1 -1
- package/dist/cjs/resources/counterparties.js +17 -0
- package/dist/cjs/resources/counterparties.js.map +1 -1
- package/dist/cjs/resources/folders.d.ts +51 -10
- package/dist/cjs/resources/folders.d.ts.map +1 -1
- package/dist/cjs/resources/folders.js +36 -5
- package/dist/cjs/resources/folders.js.map +1 -1
- package/dist/cjs/resources/history.d.ts +20 -2
- package/dist/cjs/resources/history.d.ts.map +1 -1
- package/dist/cjs/resources/history.js.map +1 -1
- package/dist/cjs/resources/me.d.ts +27 -4
- package/dist/cjs/resources/me.d.ts.map +1 -1
- package/dist/cjs/resources/me.js +22 -1
- package/dist/cjs/resources/me.js.map +1 -1
- package/dist/cjs/resources/members.d.ts +19 -4
- package/dist/cjs/resources/members.d.ts.map +1 -1
- package/dist/cjs/resources/members.js +15 -6
- package/dist/cjs/resources/members.js.map +1 -1
- package/dist/cjs/resources/operations.d.ts +64 -8
- package/dist/cjs/resources/operations.d.ts.map +1 -1
- package/dist/cjs/resources/operations.js +26 -2
- package/dist/cjs/resources/operations.js.map +1 -1
- package/dist/cjs/resources/registries.d.ts +87 -9
- package/dist/cjs/resources/registries.d.ts.map +1 -1
- package/dist/cjs/resources/registries.js +54 -11
- package/dist/cjs/resources/registries.js.map +1 -1
- package/dist/cjs/resources/reports.d.ts +300 -41
- package/dist/cjs/resources/reports.d.ts.map +1 -1
- package/dist/cjs/resources/reports.js +135 -7
- package/dist/cjs/resources/reports.js.map +1 -1
- package/dist/cjs/resources/sharing.d.ts +61 -10
- package/dist/cjs/resources/sharing.d.ts.map +1 -1
- package/dist/cjs/resources/sharing.js +51 -4
- package/dist/cjs/resources/sharing.js.map +1 -1
- package/dist/cjs/resources/transfers.d.ts +26 -4
- package/dist/cjs/resources/transfers.d.ts.map +1 -1
- package/dist/cjs/resources/transfers.js +23 -1
- package/dist/cjs/resources/transfers.js.map +1 -1
- package/dist/cjs/resources/types.d.ts +20 -0
- package/dist/cjs/resources/types.d.ts.map +1 -1
- package/dist/cjs/units.d.ts.map +1 -1
- package/dist/cjs/units.js +18 -2
- package/dist/cjs/units.js.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client.d.ts +67 -22
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +38 -2
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/core/errors.d.ts +30 -10
- package/dist/esm/core/errors.d.ts.map +1 -1
- package/dist/esm/core/errors.js +47 -15
- package/dist/esm/core/errors.js.map +1 -1
- package/dist/esm/core/gated.d.ts +21 -3
- package/dist/esm/core/gated.d.ts.map +1 -1
- package/dist/esm/core/gated.js +12 -3
- package/dist/esm/core/gated.js.map +1 -1
- package/dist/esm/core/http.d.ts +12 -8
- package/dist/esm/core/http.d.ts.map +1 -1
- package/dist/esm/core/http.js +131 -41
- package/dist/esm/core/http.js.map +1 -1
- package/dist/esm/core/pagination.d.ts +28 -1
- package/dist/esm/core/pagination.d.ts.map +1 -1
- package/dist/esm/core/pagination.js +36 -1
- package/dist/esm/core/pagination.js.map +1 -1
- package/dist/esm/generated/operations.js +1 -1
- package/dist/esm/generated/types.d.ts +948 -172
- package/dist/esm/generated/types.d.ts.map +1 -1
- package/dist/esm/index.d.ts +32 -8
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +17 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/resources/addresses.d.ts +22 -8
- package/dist/esm/resources/addresses.d.ts.map +1 -1
- package/dist/esm/resources/addresses.js +7 -1
- package/dist/esm/resources/addresses.js.map +1 -1
- package/dist/esm/resources/admin.d.ts +150 -25
- package/dist/esm/resources/admin.d.ts.map +1 -1
- package/dist/esm/resources/admin.js +94 -23
- package/dist/esm/resources/admin.js.map +1 -1
- package/dist/esm/resources/approvals.d.ts +46 -5
- package/dist/esm/resources/approvals.d.ts.map +1 -1
- package/dist/esm/resources/approvals.js +27 -4
- package/dist/esm/resources/approvals.js.map +1 -1
- package/dist/esm/resources/balances.d.ts +152 -16
- package/dist/esm/resources/balances.d.ts.map +1 -1
- package/dist/esm/resources/balances.js +9 -5
- package/dist/esm/resources/balances.js.map +1 -1
- package/dist/esm/resources/categories.d.ts +93 -21
- package/dist/esm/resources/categories.d.ts.map +1 -1
- package/dist/esm/resources/categories.js +65 -18
- package/dist/esm/resources/categories.js.map +1 -1
- package/dist/esm/resources/counterparties.d.ts +26 -3
- package/dist/esm/resources/counterparties.d.ts.map +1 -1
- package/dist/esm/resources/counterparties.js +17 -0
- package/dist/esm/resources/counterparties.js.map +1 -1
- package/dist/esm/resources/folders.d.ts +51 -10
- package/dist/esm/resources/folders.d.ts.map +1 -1
- package/dist/esm/resources/folders.js +36 -5
- package/dist/esm/resources/folders.js.map +1 -1
- package/dist/esm/resources/history.d.ts +20 -2
- package/dist/esm/resources/history.d.ts.map +1 -1
- package/dist/esm/resources/history.js.map +1 -1
- package/dist/esm/resources/me.d.ts +27 -4
- package/dist/esm/resources/me.d.ts.map +1 -1
- package/dist/esm/resources/me.js +22 -1
- package/dist/esm/resources/me.js.map +1 -1
- package/dist/esm/resources/members.d.ts +19 -4
- package/dist/esm/resources/members.d.ts.map +1 -1
- package/dist/esm/resources/members.js +15 -6
- package/dist/esm/resources/members.js.map +1 -1
- package/dist/esm/resources/operations.d.ts +64 -8
- package/dist/esm/resources/operations.d.ts.map +1 -1
- package/dist/esm/resources/operations.js +26 -2
- package/dist/esm/resources/operations.js.map +1 -1
- package/dist/esm/resources/registries.d.ts +87 -9
- package/dist/esm/resources/registries.d.ts.map +1 -1
- package/dist/esm/resources/registries.js +54 -11
- package/dist/esm/resources/registries.js.map +1 -1
- package/dist/esm/resources/reports.d.ts +300 -41
- package/dist/esm/resources/reports.d.ts.map +1 -1
- package/dist/esm/resources/reports.js +135 -7
- package/dist/esm/resources/reports.js.map +1 -1
- package/dist/esm/resources/sharing.d.ts +61 -10
- package/dist/esm/resources/sharing.d.ts.map +1 -1
- package/dist/esm/resources/sharing.js +51 -4
- package/dist/esm/resources/sharing.js.map +1 -1
- package/dist/esm/resources/transfers.d.ts +26 -4
- package/dist/esm/resources/transfers.d.ts.map +1 -1
- package/dist/esm/resources/transfers.js +23 -1
- package/dist/esm/resources/transfers.js.map +1 -1
- package/dist/esm/resources/types.d.ts +20 -0
- package/dist/esm/resources/types.d.ts.map +1 -1
- package/dist/esm/units.d.ts.map +1 -1
- package/dist/esm/units.js +18 -2
- package/dist/esm/units.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/docs/concepts.md +191 -0
- package/docs/errors.md +471 -0
- package/package.json +7 -6
- package/src/client.ts +89 -25
- package/src/core/errors.ts +49 -15
- package/src/core/gated.ts +22 -4
- package/src/core/http.ts +156 -46
- package/src/core/pagination.ts +38 -1
- package/src/generated/operations.ts +1 -1
- package/src/generated/types.ts +983 -173
- package/src/index.ts +64 -7
- package/src/resources/addresses.ts +23 -8
- package/src/resources/admin.ts +186 -33
- package/src/resources/approvals.ts +55 -9
- package/src/resources/balances.ts +186 -14
- package/src/resources/categories.ts +125 -30
- package/src/resources/counterparties.ts +23 -6
- package/src/resources/folders.ts +74 -18
- package/src/resources/history.ts +27 -2
- package/src/resources/me.ts +30 -5
- package/src/resources/members.ts +26 -7
- package/src/resources/operations.ts +73 -8
- package/src/resources/registries.ts +90 -11
- package/src/resources/reports.ts +348 -67
- package/src/resources/sharing.ts +71 -18
- package/src/resources/transfers.ts +33 -5
- package/src/resources/types.ts +20 -0
- package/src/units.ts +19 -2
- package/src/version.ts +1 -1
|
@@ -1,18 +1,142 @@
|
|
|
1
1
|
import { seg, type HttpClient } from '../core/http.js'
|
|
2
2
|
import type { PageParams } from '../core/pagination.js'
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
BalancesAsOf,
|
|
5
|
+
BalancesAsOfAccount,
|
|
6
|
+
LedgerAccountItem,
|
|
7
|
+
LedgerEntriesPage,
|
|
8
|
+
LedgerEntry,
|
|
9
|
+
LedgerPosting as GeneratedLedgerPosting,
|
|
10
|
+
VaultBalancesResponse,
|
|
11
|
+
} from '../generated/types.js'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* What a ledger account is FOR. A strict alias of the generated enum.
|
|
15
|
+
*
|
|
16
|
+
* `available` (spendable) and `reserved` (held for a transfer in flight)
|
|
17
|
+
* belong to an ADDRESS. `external` and `adjustment` are vault-level: they are
|
|
18
|
+
* the far side of the double entry — the outside world, and manual
|
|
19
|
+
* corrections — and belong to no address, which is why
|
|
20
|
+
* `LedgerAccountItem.address` is nullable.
|
|
21
|
+
*/
|
|
22
|
+
export type LedgerPurpose = LedgerAccountItem['purpose']
|
|
4
23
|
|
|
5
24
|
export interface BalancesParams extends PageParams {
|
|
6
25
|
/** Roll up the whole vault instead of listing per address. */
|
|
7
26
|
summary?: boolean | undefined
|
|
8
27
|
addressId?: string | undefined
|
|
9
28
|
token?: string | undefined
|
|
10
|
-
/**
|
|
11
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Narrows `accounts` ONLY. `totals` ignores it and always reports
|
|
31
|
+
* `available` plus `reserved`, so `purpose: 'external'` lists the
|
|
32
|
+
* vault-level accounts beside totals that do not count them — the two
|
|
33
|
+
* halves of the answer are not filtered the same way.
|
|
34
|
+
*/
|
|
35
|
+
purpose?: LedgerPurpose | undefined
|
|
12
36
|
/** Include addresses shared with you. Off by default. */
|
|
13
37
|
includeShared?: boolean | undefined
|
|
14
38
|
}
|
|
15
39
|
|
|
40
|
+
/**
|
|
41
|
+
* `balances/as-of` parameters, beyond the moment itself.
|
|
42
|
+
*
|
|
43
|
+
* A superset of what `list()` takes: a replay can also be narrowed to a token
|
|
44
|
+
* id or a folder.
|
|
45
|
+
*
|
|
46
|
+
* Written by hand, like every query type in this package: the generator emits
|
|
47
|
+
* schemas and never looks at `parameters`, so there is no generated shape to
|
|
48
|
+
* alias. `test/queryParams.test.ts` holds it to the document instead — a
|
|
49
|
+
* parameter the endpoint declares and this interface lacks fails there.
|
|
50
|
+
*/
|
|
51
|
+
export interface BalancesAsOfParams {
|
|
52
|
+
/** Token code, e.g. `usdt`. Ignored when `tokenId` is given. */
|
|
53
|
+
token?: string | undefined
|
|
54
|
+
/** Registry token id. Wins over `token`. */
|
|
55
|
+
tokenId?: string | undefined
|
|
56
|
+
addressId?: string | undefined
|
|
57
|
+
/**
|
|
58
|
+
* Every address in the folder, by its CURRENT membership — a replay of past
|
|
59
|
+
* balances through today's folder. REPLACES `addressId` rather than
|
|
60
|
+
* intersecting with it, so sending both silently drops `addressId`.
|
|
61
|
+
*/
|
|
62
|
+
folderId?: string | undefined
|
|
63
|
+
purpose?: LedgerPurpose | undefined
|
|
64
|
+
/** Totals only. See the overloads: `accounts` is then ABSENT, not empty. */
|
|
65
|
+
summary?: boolean | undefined
|
|
66
|
+
includeShared?: boolean | undefined
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* What `asOf` answers WITHOUT `summary` — the body with `accounts` present.
|
|
71
|
+
*
|
|
72
|
+
* The generated `BalancesAsOf` describes both modes with one schema, so its
|
|
73
|
+
* `accounts` is optional: absent under `summary: true`, always there
|
|
74
|
+
* otherwise (an empty array when nothing moved before the moment). This is
|
|
75
|
+
* the second half of that sentence as a type, so a call that did not ask for
|
|
76
|
+
* a summary is not made to check for a key that cannot be missing.
|
|
77
|
+
*/
|
|
78
|
+
export type BalancesAsOfWithAccounts = BalancesAsOf & { accounts: BalancesAsOfAccount[] }
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* What `asOf` answers under `summary: true` — the same body WITHOUT
|
|
82
|
+
* `accounts`.
|
|
83
|
+
*
|
|
84
|
+
* Not an empty array: the key is absent, which is how the API tells "accounts
|
|
85
|
+
* were not asked for" from "there are none". The document says the same —
|
|
86
|
+
* `BalancesAsOf.accounts` is optional — and this type is the summary half of
|
|
87
|
+
* it, with the key removed rather than left optional.
|
|
88
|
+
*
|
|
89
|
+
* Spellable without importing it: `Omit<BalancesAsOf, 'accounts'>`.
|
|
90
|
+
*/
|
|
91
|
+
export type BalancesAsOfSummary = Omit<BalancesAsOf, 'accounts'>
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* One side of a ledger entry. A strict alias of the generated schema.
|
|
95
|
+
*
|
|
96
|
+
* Signed, with no `direction` field: which way the money went IS the sign of
|
|
97
|
+
* `amountRawSigned` — negative means debited from that account. A COMPLETE
|
|
98
|
+
* entry's postings sum to zero; see `entries` for why the ones you are shown
|
|
99
|
+
* may not. `ownerId` is the address id, or the vault id for a vault-level
|
|
100
|
+
* account, and `amountDecimalSigned` falls back to the raw figure when the
|
|
101
|
+
* posting's token is not in the registry.
|
|
102
|
+
*/
|
|
103
|
+
export type LedgerPosting = GeneratedLedgerPosting
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The values `entryType` takes, as the journal REPORTS them.
|
|
107
|
+
*
|
|
108
|
+
* Stored as `reserve`/`confirm`/`release` and renamed on the way out, which
|
|
109
|
+
* is why the filter accepts either spelling: `entryType: 'reserve'` and
|
|
110
|
+
* `entryType: 'transfer_reserve'` select the same rows. `topup`, `adjustment`
|
|
111
|
+
* and `genesis` have no transfer stage and are not renamed. `genesis` is the
|
|
112
|
+
* opening correction written when the ledger was first backfilled; nothing
|
|
113
|
+
* creates new ones.
|
|
114
|
+
*
|
|
115
|
+
* Kept by hand because the document does not carry it as a type: the
|
|
116
|
+
* generated `LedgerEntry.entryType` is a bare `string` whose DESCRIPTION
|
|
117
|
+
* lists these six. The API does not close the list either — a stored kind it
|
|
118
|
+
* has no name for is passed through as it is — so this union types the
|
|
119
|
+
* FILTER, where a misspelling answers an empty page rather than an error,
|
|
120
|
+
* and is not forced onto the entries that come back.
|
|
121
|
+
*/
|
|
122
|
+
export type LedgerEntryType =
|
|
123
|
+
| 'transfer_reserve'
|
|
124
|
+
| 'transfer_confirm'
|
|
125
|
+
| 'transfer_refund'
|
|
126
|
+
| 'topup'
|
|
127
|
+
| 'adjustment'
|
|
128
|
+
| 'genesis'
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* One ledger entry. A strict alias of the generated `LedgerEntry`, kept under
|
|
132
|
+
* its earlier name.
|
|
133
|
+
*
|
|
134
|
+
* `token` is the entry's token by its FIRST posting, taken before postings
|
|
135
|
+
* are filtered for the caller — so it is present even when `postings` comes
|
|
136
|
+
* back empty for you.
|
|
137
|
+
*/
|
|
138
|
+
export type LedgerEntryItem = LedgerEntry
|
|
139
|
+
|
|
16
140
|
/**
|
|
17
141
|
* Balances and the ledger behind them.
|
|
18
142
|
*
|
|
@@ -38,31 +162,79 @@ export class BalancesResource {
|
|
|
38
162
|
)
|
|
39
163
|
}
|
|
40
164
|
|
|
41
|
-
/**
|
|
42
|
-
|
|
43
|
-
|
|
165
|
+
/**
|
|
166
|
+
* Balances as they stood at a moment in time, replayed from the ledger.
|
|
167
|
+
*
|
|
168
|
+
* `at` is positional because it is required — a replay with no instant is
|
|
169
|
+
* not a replay. `totals` covers `available` and `reserved` only; the
|
|
170
|
+
* vault-level accounts appear in `accounts` and never in the totals.
|
|
171
|
+
*
|
|
172
|
+
* UNITS DIFFER FROM `list()`. In `totals`, `available` and `reserved` are
|
|
173
|
+
* DECIMAL here — duplicates of `availableDecimal`/`reservedDecimal` — while
|
|
174
|
+
* the fields of the same name on `list()` are raw smallest units. Raw
|
|
175
|
+
* figures exist only per account, in `accounts[].balance`. Read the totals
|
|
176
|
+
* with `parseDecimal`, not `amount`.
|
|
177
|
+
*/
|
|
178
|
+
asOf(
|
|
179
|
+
at: string,
|
|
180
|
+
params?: BalancesAsOfParams & { summary?: false | undefined },
|
|
181
|
+
): Promise<BalancesAsOfWithAccounts>
|
|
182
|
+
/** `summary: true` — totals only, and the body carries no `accounts` key. */
|
|
183
|
+
asOf(
|
|
184
|
+
at: string,
|
|
185
|
+
params: BalancesAsOfParams & { summary: true },
|
|
186
|
+
): Promise<BalancesAsOfSummary>
|
|
187
|
+
/**
|
|
188
|
+
* `summary` decided at runtime. The answer is then one shape or the other,
|
|
189
|
+
* so this signature hands back the union rather than guessing: narrow it
|
|
190
|
+
* with `'accounts' in result`.
|
|
191
|
+
*/
|
|
192
|
+
asOf(
|
|
193
|
+
at: string,
|
|
194
|
+
params: BalancesAsOfParams,
|
|
195
|
+
): Promise<BalancesAsOfWithAccounts | BalancesAsOfSummary>
|
|
196
|
+
asOf(
|
|
197
|
+
at: string,
|
|
198
|
+
params: BalancesAsOfParams = {},
|
|
199
|
+
): Promise<BalancesAsOfWithAccounts | BalancesAsOfSummary> {
|
|
200
|
+
return this.#http.request<BalancesAsOfWithAccounts | BalancesAsOfSummary>(
|
|
44
201
|
'GET',
|
|
45
202
|
`/api/v1/vaults/${this.#vault}/balances/as-of`,
|
|
46
203
|
{ query: { at, ...params } },
|
|
47
204
|
)
|
|
48
205
|
}
|
|
49
206
|
|
|
50
|
-
/**
|
|
207
|
+
/**
|
|
208
|
+
* The raw ledger. Append-only: corrections arrive as reversing entries.
|
|
209
|
+
*
|
|
210
|
+
* Non-admins see only the entries that touch their own addresses, and
|
|
211
|
+
* within such an entry only their own postings plus the vault-level ones.
|
|
212
|
+
* The postings of a page therefore need not sum to zero, even though every
|
|
213
|
+
* complete entry does.
|
|
214
|
+
*/
|
|
51
215
|
entries(
|
|
52
216
|
params: PageParams & {
|
|
217
|
+
/**
|
|
218
|
+
* Entries with a posting on this address. For a non-admin it narrows
|
|
219
|
+
* WITHIN their own addresses: somebody else's id answers an empty page,
|
|
220
|
+
* not a 403.
|
|
221
|
+
*/
|
|
53
222
|
addressId?: string
|
|
54
|
-
/**
|
|
55
|
-
entryType?:
|
|
56
|
-
operationType?:
|
|
223
|
+
/** Either spelling of the stage — see `LedgerEntryType`. */
|
|
224
|
+
entryType?: LedgerEntryType | 'reserve' | 'confirm' | 'release' | undefined
|
|
225
|
+
operationType?: 'deposit' | 'transfer' | undefined
|
|
226
|
+
/** The transfer or deposit id. Only applied together with `operationType`. */
|
|
57
227
|
operationId?: string
|
|
58
228
|
token?: string
|
|
59
229
|
tokenId?: string
|
|
60
230
|
from?: string
|
|
61
231
|
to?: string
|
|
62
232
|
} = {},
|
|
63
|
-
): Promise<
|
|
64
|
-
return this.#http.request(
|
|
65
|
-
|
|
66
|
-
|
|
233
|
+
): Promise<LedgerEntriesPage> {
|
|
234
|
+
return this.#http.request<LedgerEntriesPage>(
|
|
235
|
+
'GET',
|
|
236
|
+
`/api/v1/vaults/${this.#vault}/ledger/entries`,
|
|
237
|
+
{ query: { ...params } },
|
|
238
|
+
)
|
|
67
239
|
}
|
|
68
240
|
}
|
|
@@ -2,6 +2,9 @@ import { seg, type HttpClient } from '../core/http.js'
|
|
|
2
2
|
import { toGated, type Gated } from '../core/gated.js'
|
|
3
3
|
import type { PageParams } from '../core/pagination.js'
|
|
4
4
|
import type {
|
|
5
|
+
AddOperationCategoryApproverBody,
|
|
6
|
+
AddOperationCategoryFieldBody,
|
|
7
|
+
AddOperationCategoryGrantBody,
|
|
5
8
|
ApprovalRequestCreated,
|
|
6
9
|
AssignCategoryBody,
|
|
7
10
|
EditAssignmentBody,
|
|
@@ -9,13 +12,27 @@ import type {
|
|
|
9
12
|
CreateOperationCategoryBody,
|
|
10
13
|
OperationCategoriesPage,
|
|
11
14
|
OperationCategory,
|
|
15
|
+
OperationCategoryApprover,
|
|
12
16
|
OperationCategoryAssignment,
|
|
13
17
|
OperationCategoryAssignmentVersion,
|
|
18
|
+
OperationCategoryField,
|
|
19
|
+
OperationCategoryGrant,
|
|
20
|
+
OperationType as GeneratedOperationType,
|
|
14
21
|
PatchOperationCategoryBody,
|
|
22
|
+
PatchOperationCategoryFieldBody,
|
|
15
23
|
} from '../generated/types.js'
|
|
16
24
|
|
|
17
|
-
/**
|
|
18
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Operation kind in a labelling path. Exactly two values exist.
|
|
27
|
+
*
|
|
28
|
+
* A strict alias, not `string`. Because `src/index.ts` re-exports this name
|
|
29
|
+
* explicitly, and an explicit re-export beats `export type *`, the old
|
|
30
|
+
* `= string` was what consumers actually got for a schema that eight
|
|
31
|
+
* operations reference by name — so a misspelled kind compiled here and came
|
|
32
|
+
* back as a 400 from production instead. Every endpoint that takes the kind
|
|
33
|
+
* as a path segment refuses anything but these two outright.
|
|
34
|
+
*/
|
|
35
|
+
export type OperationType = GeneratedOperationType
|
|
19
36
|
|
|
20
37
|
/**
|
|
21
38
|
* Configurable labelling of operations.
|
|
@@ -74,13 +91,32 @@ export class CategoriesResource {
|
|
|
74
91
|
return this.#http.request<OperationCategory>('GET', `${this.#catalogue}/${seg(categoryId)}`)
|
|
75
92
|
}
|
|
76
93
|
|
|
77
|
-
/**
|
|
78
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Categories this person may apply to this operation, with their fields.
|
|
96
|
+
*
|
|
97
|
+
* This is the endpoint to build a labelling form from, not `list()`: it
|
|
98
|
+
* accounts for grants and for access to the operation's own address, and it
|
|
99
|
+
* leaves out archived fields. `grants` and `approvers` never come back here
|
|
100
|
+
* — that is access configuration, and only an administrator sees it.
|
|
101
|
+
*/
|
|
102
|
+
available(
|
|
103
|
+
type: OperationType,
|
|
104
|
+
operationId: string,
|
|
105
|
+
): Promise<{ items: OperationCategory[] }> {
|
|
79
106
|
return this.#http.request('GET', `${this.#assignments(type, operationId)}/available`)
|
|
80
107
|
}
|
|
81
108
|
|
|
82
|
-
/**
|
|
83
|
-
|
|
109
|
+
/**
|
|
110
|
+
* What is currently applied to an operation.
|
|
111
|
+
*
|
|
112
|
+
* Only the assignments whose values this person may see; a category they
|
|
113
|
+
* have no view access to is absent rather than empty. Within a visible one,
|
|
114
|
+
* sensitive fields come back as `null` with their keys in `redactedFields`.
|
|
115
|
+
*/
|
|
116
|
+
assignments(
|
|
117
|
+
type: OperationType,
|
|
118
|
+
operationId: string,
|
|
119
|
+
): Promise<{ items: OperationCategoryAssignment[] }> {
|
|
84
120
|
return this.#http.request('GET', this.#assignments(type, operationId))
|
|
85
121
|
}
|
|
86
122
|
|
|
@@ -129,11 +165,12 @@ export class CategoriesResource {
|
|
|
129
165
|
return toGated<OperationCategoryAssignment, ApprovalRequestCreated>(res.status, res.data)
|
|
130
166
|
}
|
|
131
167
|
|
|
168
|
+
/** Soft: the assignment goes to `removed` and its history survives. */
|
|
132
169
|
removeAssignment(
|
|
133
170
|
type: OperationType,
|
|
134
171
|
operationId: string,
|
|
135
172
|
assignmentId: string,
|
|
136
|
-
): Promise<
|
|
173
|
+
): Promise<{ removed: boolean }> {
|
|
137
174
|
return this.#http.request(
|
|
138
175
|
'DELETE',
|
|
139
176
|
`${this.#assignments(type, operationId)}/${seg(assignmentId)}`,
|
|
@@ -166,12 +203,27 @@ export class CategoriesResource {
|
|
|
166
203
|
|
|
167
204
|
// --- administrator only -------------------------------------------------
|
|
168
205
|
|
|
169
|
-
/**
|
|
206
|
+
/**
|
|
207
|
+
* Creates a category. Administrator only.
|
|
208
|
+
*
|
|
209
|
+
* `viewScope`, `assignScope` and `editScope` say what the category opens to
|
|
210
|
+
* people WITHOUT a grant, and each takes one of two values: `owner_only` —
|
|
211
|
+
* nothing beyond access through the operation's own address and the
|
|
212
|
+
* category's grants — or `vault_members`, every member of the vault.
|
|
213
|
+
*
|
|
214
|
+
* The API still accepts a third spelling on input, `restricted`, as an
|
|
215
|
+
* alias of `owner_only`: it is stored as `owner_only` and never comes back
|
|
216
|
+
* in an answer. `CategoryAccessScope` leaves it out on purpose, so it does
|
|
217
|
+
* not compile here — send `owner_only`.
|
|
218
|
+
*/
|
|
170
219
|
create(input: CreateOperationCategoryBody): Promise<OperationCategory> {
|
|
171
220
|
return this.#http.request<OperationCategory>('POST', this.#catalogue, { body: input })
|
|
172
221
|
}
|
|
173
222
|
|
|
174
|
-
/**
|
|
223
|
+
/**
|
|
224
|
+
* Administrator only. `key` cannot be changed. The three scopes take the
|
|
225
|
+
* same two values as on `create`.
|
|
226
|
+
*/
|
|
175
227
|
update(categoryId: string, input: PatchOperationCategoryBody): Promise<OperationCategory> {
|
|
176
228
|
return this.#http.request<OperationCategory>(
|
|
177
229
|
'PATCH',
|
|
@@ -180,16 +232,42 @@ export class CategoriesResource {
|
|
|
180
232
|
)
|
|
181
233
|
}
|
|
182
234
|
|
|
183
|
-
/**
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
235
|
+
/**
|
|
236
|
+
* Administrator only. A field's `key` and `type` are fixed once created.
|
|
237
|
+
*
|
|
238
|
+
* `currencyFieldKey` is only for `type: 'currency'` and must name a sibling
|
|
239
|
+
* field of this same category that holds the ticker; the server refuses a
|
|
240
|
+
* dangling or wrongly typed link with 400 `CATEGORY_FIELD_LINK`.
|
|
241
|
+
*/
|
|
242
|
+
addField(
|
|
243
|
+
categoryId: string,
|
|
244
|
+
input: AddOperationCategoryFieldBody,
|
|
245
|
+
): Promise<OperationCategoryField> {
|
|
246
|
+
return this.#http.request<OperationCategoryField>(
|
|
247
|
+
'POST',
|
|
248
|
+
`${this.#catalogue}/${seg(categoryId)}/fields`,
|
|
249
|
+
{ body: input },
|
|
250
|
+
)
|
|
188
251
|
}
|
|
189
252
|
|
|
190
|
-
/**
|
|
191
|
-
|
|
192
|
-
|
|
253
|
+
/**
|
|
254
|
+
* Administrator only.
|
|
255
|
+
*
|
|
256
|
+
* `key` and `type` are absent from the body on purpose — they are
|
|
257
|
+
* immutable, since stored values, reports and snapshots are keyed by them;
|
|
258
|
+
* `scale` is not patchable either, so a field's precision is decided once.
|
|
259
|
+
* For `select`, `optionsJson` is the FULL new list and options may only be
|
|
260
|
+
* added. `archived: true` is how a field is retired, because a field with
|
|
261
|
+
* history cannot be deleted. Passing `currencyFieldKey: null` drops the
|
|
262
|
+
* amount↔ticker link, after which reports go back to adding different
|
|
263
|
+
* currencies into one meaningless total.
|
|
264
|
+
*/
|
|
265
|
+
updateField(
|
|
266
|
+
categoryId: string,
|
|
267
|
+
fieldId: string,
|
|
268
|
+
input: PatchOperationCategoryFieldBody,
|
|
269
|
+
): Promise<OperationCategoryField> {
|
|
270
|
+
return this.#http.request<OperationCategoryField>(
|
|
193
271
|
'PATCH',
|
|
194
272
|
`${this.#catalogue}/${seg(categoryId)}/fields/${seg(fieldId)}`,
|
|
195
273
|
{ body: input },
|
|
@@ -197,29 +275,46 @@ export class CategoriesResource {
|
|
|
197
275
|
}
|
|
198
276
|
|
|
199
277
|
/** Administrator only. Who approves edits gated by `approvalScope`. */
|
|
200
|
-
addApprover(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
278
|
+
addApprover(
|
|
279
|
+
categoryId: string,
|
|
280
|
+
input: AddOperationCategoryApproverBody,
|
|
281
|
+
): Promise<OperationCategoryApprover> {
|
|
282
|
+
return this.#http.request<OperationCategoryApprover>(
|
|
283
|
+
'POST',
|
|
284
|
+
`${this.#catalogue}/${seg(categoryId)}/approvers`,
|
|
285
|
+
{ body: input },
|
|
286
|
+
)
|
|
204
287
|
}
|
|
205
288
|
|
|
206
|
-
/** Administrator only. */
|
|
207
|
-
removeApprover(categoryId: string, approverId: string): Promise<
|
|
289
|
+
/** Administrator only. `deleted: false` means there was nothing to remove. */
|
|
290
|
+
removeApprover(categoryId: string, approverId: string): Promise<{ deleted: boolean }> {
|
|
208
291
|
return this.#http.request(
|
|
209
292
|
'DELETE',
|
|
210
293
|
`${this.#catalogue}/${seg(categoryId)}/approvers/${seg(approverId)}`,
|
|
211
294
|
)
|
|
212
295
|
}
|
|
213
296
|
|
|
214
|
-
/**
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
297
|
+
/**
|
|
298
|
+
* Administrator only. Who may see or edit values of this category.
|
|
299
|
+
*
|
|
300
|
+
* Idempotent, like every grant in this API: calling it again for the same
|
|
301
|
+
* subject updates the rights and revives a revoked grant, so there is no
|
|
302
|
+
* "already exists" error to handle. `canEdit` implies `canView` — the
|
|
303
|
+
* server fills it in, because the other combination is unenforceable.
|
|
304
|
+
*/
|
|
305
|
+
addGrant(
|
|
306
|
+
categoryId: string,
|
|
307
|
+
input: AddOperationCategoryGrantBody,
|
|
308
|
+
): Promise<OperationCategoryGrant> {
|
|
309
|
+
return this.#http.request<OperationCategoryGrant>(
|
|
310
|
+
'POST',
|
|
311
|
+
`${this.#catalogue}/${seg(categoryId)}/grants`,
|
|
312
|
+
{ body: input },
|
|
313
|
+
)
|
|
219
314
|
}
|
|
220
315
|
|
|
221
|
-
/** Administrator only. */
|
|
222
|
-
removeGrant(categoryId: string, grantId: string): Promise<
|
|
316
|
+
/** Administrator only. Soft revoke; `revoked: false` means no such grant. */
|
|
317
|
+
removeGrant(categoryId: string, grantId: string): Promise<{ revoked: boolean }> {
|
|
223
318
|
return this.#http.request(
|
|
224
319
|
'DELETE',
|
|
225
320
|
`${this.#catalogue}/${seg(categoryId)}/grants/${seg(grantId)}`,
|
|
@@ -110,15 +110,23 @@ export class CounterpartiesResource {
|
|
|
110
110
|
return toGated<CounterpartyAddressCreated, ApprovalRequestCreated>(res.status, res.data)
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Narrows any allow-list built on this counterparty, so it is gated like
|
|
115
|
+
* the rest — under the `counterparty_update` policy, not one of its own.
|
|
116
|
+
*
|
|
117
|
+
* Operations already attributed to this address KEEP the counterparty: at
|
|
118
|
+
* the time they happened the address did belong to it, and that is a
|
|
119
|
+
* historical fact. Only new operations stop matching.
|
|
120
|
+
*/
|
|
113
121
|
async removeAddress(
|
|
114
122
|
counterpartyId: string,
|
|
115
123
|
addressId: string,
|
|
116
|
-
): Promise<Gated<
|
|
124
|
+
): Promise<Gated<{ deleted: true }, ApprovalRequestCreated>> {
|
|
117
125
|
const res = await this.#http.requestRaw<unknown>(
|
|
118
126
|
'DELETE',
|
|
119
127
|
`${this.#base}/${seg(counterpartyId)}/addresses/${seg(addressId)}`,
|
|
120
128
|
)
|
|
121
|
-
return toGated<
|
|
129
|
+
return toGated<{ deleted: true }, ApprovalRequestCreated>(res.status, res.data)
|
|
122
130
|
}
|
|
123
131
|
}
|
|
124
132
|
|
|
@@ -173,24 +181,33 @@ export class CounterpartyGroupsResource {
|
|
|
173
181
|
return toGated<CounterpartyGroup, ApprovalRequestCreated>(res.status, res.data)
|
|
174
182
|
}
|
|
175
183
|
|
|
184
|
+
/**
|
|
185
|
+
* WIDENS any allow-list built on this group, and does so the moment it
|
|
186
|
+
* applies — which is why it is gated by its own policy
|
|
187
|
+
* (`counterparty_group_add`) rather than riding on the group's update.
|
|
188
|
+
*/
|
|
176
189
|
async addMember(
|
|
177
190
|
groupId: string,
|
|
178
191
|
counterpartyId: string,
|
|
179
|
-
): Promise<Gated<
|
|
192
|
+
): Promise<Gated<{ added: true }, ApprovalRequestCreated>> {
|
|
180
193
|
const res = await this.#http.requestRaw<unknown>('POST', `${this.#base}/${seg(groupId)}/members`, {
|
|
181
194
|
body: { counterpartyId },
|
|
182
195
|
})
|
|
183
|
-
return toGated<
|
|
196
|
+
return toGated<{ added: true }, ApprovalRequestCreated>(res.status, res.data)
|
|
184
197
|
}
|
|
185
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Payments to this counterparty under the group's allow-list stop at once.
|
|
201
|
+
* `removed: false` means it was not in the group — not a failure.
|
|
202
|
+
*/
|
|
186
203
|
async removeMember(
|
|
187
204
|
groupId: string,
|
|
188
205
|
counterpartyId: string,
|
|
189
|
-
): Promise<Gated<
|
|
206
|
+
): Promise<Gated<{ removed: boolean }, ApprovalRequestCreated>> {
|
|
190
207
|
const res = await this.#http.requestRaw<unknown>(
|
|
191
208
|
'DELETE',
|
|
192
209
|
`${this.#base}/${seg(groupId)}/members/${seg(counterpartyId)}`,
|
|
193
210
|
)
|
|
194
|
-
return toGated<
|
|
211
|
+
return toGated<{ removed: boolean }, ApprovalRequestCreated>(res.status, res.data)
|
|
195
212
|
}
|
|
196
213
|
}
|
package/src/resources/folders.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { seg, type HttpClient } from '../core/http.js'
|
|
2
2
|
import type {
|
|
3
3
|
AddFolderAddressBody,
|
|
4
|
+
AddressAccessGrant,
|
|
4
5
|
AddressGroup,
|
|
5
6
|
AddressGroupDetail,
|
|
6
7
|
AddressGroupsList,
|
|
8
|
+
AddressSharesList,
|
|
7
9
|
CreateAddressGroupBody,
|
|
8
10
|
GrantGroupBody,
|
|
9
11
|
ParticipantsResponse,
|
|
10
12
|
PatchAddressGroupBody,
|
|
11
13
|
PatchGroupGrantBody,
|
|
14
|
+
ShareGrantCreated,
|
|
12
15
|
} from '../generated/types.js'
|
|
13
16
|
|
|
14
17
|
/**
|
|
@@ -62,39 +65,92 @@ export class FoldersResource {
|
|
|
62
65
|
})
|
|
63
66
|
}
|
|
64
67
|
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
/** Deleting takes the membership rows with it, and the grants on the folder. */
|
|
69
|
+
delete(folderId: string): Promise<{ deleted: boolean }> {
|
|
70
|
+
return this.#http.request<{ deleted: boolean }>('DELETE', `${this.#base}/${seg(folderId)}`)
|
|
67
71
|
}
|
|
68
72
|
|
|
69
|
-
addAddress(folderId: string, input: AddFolderAddressBody): Promise<
|
|
70
|
-
return this.#http.request
|
|
73
|
+
addAddress(folderId: string, input: AddFolderAddressBody): Promise<{ added: boolean }> {
|
|
74
|
+
return this.#http.request<{ added: boolean }>(
|
|
75
|
+
'POST',
|
|
76
|
+
`${this.#base}/${seg(folderId)}/members`,
|
|
77
|
+
{ body: input },
|
|
78
|
+
)
|
|
71
79
|
}
|
|
72
80
|
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Taking an address out ends access that came FROM THE FOLDER. Grants on
|
|
83
|
+
* the address itself are untouched — they are a separate relationship.
|
|
84
|
+
*/
|
|
85
|
+
removeAddress(folderId: string, addressId: string): Promise<{ removed: boolean }> {
|
|
86
|
+
return this.#http.request<{ removed: boolean }>(
|
|
75
87
|
'DELETE',
|
|
76
88
|
`${this.#base}/${seg(folderId)}/members/${seg(addressId)}`,
|
|
77
89
|
)
|
|
78
90
|
}
|
|
79
91
|
|
|
80
|
-
/**
|
|
81
|
-
|
|
82
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Grants on the folder itself — everything in it becomes reachable,
|
|
94
|
+
* including addresses added later.
|
|
95
|
+
*
|
|
96
|
+
* The same shape as the grants on a single address, and each entry carries
|
|
97
|
+
* `role`: do not rebuild it from the flags on the client, or you end up
|
|
98
|
+
* with a second translation that diverges from the first on the next right
|
|
99
|
+
* that is added.
|
|
100
|
+
*
|
|
101
|
+
* Owners of the addresses inside are NOT listed — their access comes from
|
|
102
|
+
* ownership, not from a grant. For people rather than grants, ask
|
|
103
|
+
* `participants()`.
|
|
104
|
+
*/
|
|
105
|
+
grants(folderId: string): Promise<AddressSharesList> {
|
|
106
|
+
return this.#http.request<AddressSharesList>(
|
|
107
|
+
'GET',
|
|
108
|
+
`${this.#base}/${seg(folderId)}/grants`,
|
|
109
|
+
)
|
|
83
110
|
}
|
|
84
111
|
|
|
85
|
-
/**
|
|
86
|
-
|
|
87
|
-
|
|
112
|
+
/**
|
|
113
|
+
* Idempotent: repeating it for the same pair updates the rights and revives
|
|
114
|
+
* a revoked grant — no 409 to catch, no read-then-PATCH dance.
|
|
115
|
+
*
|
|
116
|
+
* With `subjects[]` it answers a batch (`results[]`, one entry per subject,
|
|
117
|
+
* each independent); with a single subject it answers the grant itself,
|
|
118
|
+
* hence the union. The all-failed case behaves as it does on
|
|
119
|
+
* `sharing.share` — 400 carrying the same `results[]` body
|
|
120
|
+
* (`ShareBatchAllRejected`), which the SDK surfaces as a `CoreError` with
|
|
121
|
+
* the body in `details`.
|
|
122
|
+
*/
|
|
123
|
+
grant(folderId: string, input: GrantGroupBody): Promise<ShareGrantCreated> {
|
|
124
|
+
return this.#http.request<ShareGrantCreated>(
|
|
125
|
+
'POST',
|
|
126
|
+
`${this.#base}/${seg(folderId)}/grants`,
|
|
127
|
+
{ body: input },
|
|
128
|
+
)
|
|
88
129
|
}
|
|
89
130
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
131
|
+
/**
|
|
132
|
+
* `role` sets view and transfer together; the individual flags are the
|
|
133
|
+
* older way in. `canCreateAddress` is not part of either role and is
|
|
134
|
+
* changed on its own.
|
|
135
|
+
*/
|
|
136
|
+
updateGrant(
|
|
137
|
+
folderId: string,
|
|
138
|
+
grantId: string,
|
|
139
|
+
input: PatchGroupGrantBody,
|
|
140
|
+
): Promise<AddressAccessGrant> {
|
|
141
|
+
return this.#http.request<AddressAccessGrant>(
|
|
142
|
+
'PATCH',
|
|
143
|
+
`${this.#base}/${seg(folderId)}/grants/${seg(grantId)}`,
|
|
144
|
+
{ body: input },
|
|
145
|
+
)
|
|
94
146
|
}
|
|
95
147
|
|
|
96
|
-
|
|
97
|
-
|
|
148
|
+
/** Soft: the row stays as `revoked` for the audit trail. Effective at once. */
|
|
149
|
+
revokeGrant(folderId: string, grantId: string): Promise<{ revoked: boolean }> {
|
|
150
|
+
return this.#http.request<{ revoked: boolean }>(
|
|
151
|
+
'DELETE',
|
|
152
|
+
`${this.#base}/${seg(folderId)}/grants/${seg(grantId)}`,
|
|
153
|
+
)
|
|
98
154
|
}
|
|
99
155
|
|
|
100
156
|
/** People who reach the folder, with the source of each person's access. */
|