@stable_sea/sdk 0.1.2 → 0.1.4

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/README.md CHANGED
@@ -34,6 +34,27 @@ carries fixed scopes, so do not send a `Stable-Sea-Account` header.
34
34
  | SDK | API contract | Credentials |
35
35
  |---|---|---|
36
36
  | `0.1.x` | `2026-07-23` | `sk_live_…` on production |
37
+ | `0.1.x` | `2026-07-23` | `sk_test_…` on sandbox |
38
+
39
+ API access enables both Live and Sandbox. In Terminal, open **API keys** and
40
+ create a key under **Test keys**. Set `baseUrl` to
41
+ `https://sandbox-api.stablesea.com` and use that `sk_test_…` key. The same client,
42
+ contract and idempotency rules apply.
43
+ See the [sandbox quickstart](https://docs.stablesea.com/api/#sandbox) for simple
44
+ instructions and the downloadable SDK test project.
45
+
46
+ Sandbox uses synthetic balances and simulated financial partners; it cannot move
47
+ real money. Production refuses Test credentials, and the stable sandbox refuses
48
+ Live credentials. Create, rotate and revoke both kinds of keys in the same
49
+ Terminal pane with the same business permissions. Live keys require a fresh
50
+ two-factor code; Test keys do not. The first
51
+ Test key prepares isolated balances of 100,000 USDC and 50,000 WTGXX; additional
52
+ keys and rotations reuse that data.
53
+
54
+ Available funds and settlement modes follow the production contract: WTGXX
55
+ supports standard and instant settlement; FLTTX uses standard settlement. An
56
+ unsupported instant order must produce the normal refusal rather than simulated
57
+ liquidity that would not exist in production.
37
58
 
38
59
  ## Idempotent writes
39
60
 
@@ -69,3 +90,11 @@ const valid = await verifyWebhookSignature(
69
90
  API request, response, pagination, and error types are generated from
70
91
  `services/backend/api/openapi.public.json` and exported as `paths`, `operations`,
71
92
  and `components`.
93
+
94
+ ## Contract changes
95
+
96
+ - `GET /v1/balances`: `chain` gains the value `solana`. A USDC balance held on
97
+ Solana (`segregated_rail: onchain_solana`) now reports `chain: "solana"`;
98
+ before this it reported `chain: "unknown"`. Code that switches on `chain`
99
+ should accept the new value, and code that keyed a Solana balance by its
100
+ `unknown` row should expect the `solana` row instead.
@@ -153,7 +153,9 @@ export interface paths {
153
153
  * List events
154
154
  * @description Lists the events recorded for the platform, newest first.
155
155
  *
156
- * SCOPING. The response covers every event this credential recorded, so one cursor sweep reconciles everything. There is no narrower scope to ask for: one credential addresses one business.
156
+ * SCOPING. The response covers every event this credential recorded except those about pay-ins and payouts, so one cursor sweep reconciles everything this API serves. There is no narrower scope to ask for: one credential addresses one business.
157
+ *
158
+ * PAY-INS AND PAYOUTS ARE NOT SERVED. An event about a pay-in or a payout is never listed, and neither is one about a held deposit, which has no /v1 transaction. That holds for events recorded before this API stopped serving payments as well. A withheld event is answered like an id that names no event, and a cursor that names one is refused like a cursor that names no event, so restart from the newest page by sending no cursor.
157
159
  *
158
160
  * FRESHNESS. An event becomes listable 60 seconds after its created_ts. Inside that window it can be retrieved by id but is not returned here. Once a page has been served, the range it covers is complete and final: no older event can appear behind a cursor that has already passed it. Retrieval by id is not lagged.
159
161
  *
@@ -183,7 +185,7 @@ export interface paths {
183
185
  *
184
186
  * FRESHNESS. Retrieval is not lagged: an event is readable as soon as it is recorded, including during the 60 seconds before it becomes listable.
185
187
  *
186
- * SCOPING. Any event this credential recorded may be retrieved, and nothing else. An id that names no event, one belonging to another business, and one recorded in the other environment are answered identically.
188
+ * SCOPING. Any event this credential recorded may be retrieved, and nothing else, with one exclusion: an event about a pay-in, a payout or a held deposit is not served, because this API never serves those. An id that names no event, one belonging to another business, one recorded in the other environment, and one withheld for that reason are answered identically.
187
189
  *
188
190
  * RETENTION. An event remains retrievable for at least 90 days after it is recorded.
189
191
  */
@@ -196,6 +198,96 @@ export interface paths {
196
198
  patch?: never;
197
199
  trace?: never;
198
200
  };
201
+ "/v1/external_wallets": {
202
+ parameters: {
203
+ query?: never;
204
+ header?: never;
205
+ path?: never;
206
+ cookie?: never;
207
+ };
208
+ /**
209
+ * List external wallets
210
+ * @description Lists the external wallets the business has connected: the addresses it whitelisted for withdrawals, each with the latest on-chain holdings of the tokens Stable Sea tracks.
211
+ *
212
+ * THESE ARE NOT STABLE SEA BALANCES. holdings is read from the chain and describes the address; it is not money Stable Sea holds, and it is never part of /v1/balances.
213
+ *
214
+ * HOLDINGS ARE READ ONLY FOR MONITORED WALLETS: enabled, cleared for withdrawals, and on a network we read (Ethereum, Stellar). Every other wallet is still listed, with holdings_status not_monitored and no holdings. Holdings are read in the background every few minutes, not on request. A reading is served for at most 15 minutes: holdings_status is ok when the latest read succeeded and stale when it failed and the last good reading is shown, and holdings_read_ts says when it was read. unavailable means there is no reading, not that the wallet is empty. A Stellar address with a memo is a shared deposit address and is answered shared_address.
215
+ *
216
+ * PAGING. limit defaults to 10 and may not exceed 100; a larger value is rejected rather than reduced. starting_after and ending_before each take an external wallet id and cannot be combined. Wallets are ordered newest first by created_ts, ties by id. A cursor that names no current wallet is rejected rather than ignored.
217
+ */
218
+ get: operations["external_wallets.list"];
219
+ put?: never;
220
+ post?: never;
221
+ delete?: never;
222
+ options?: never;
223
+ head?: never;
224
+ patch?: never;
225
+ trace?: never;
226
+ };
227
+ "/v1/external_wallets/{id}": {
228
+ parameters: {
229
+ query?: never;
230
+ header?: never;
231
+ path?: never;
232
+ cookie?: never;
233
+ };
234
+ /**
235
+ * Retrieve an external wallet
236
+ * @description Retrieves one external wallet by id, with its latest on-chain holdings when the wallet is monitored.
237
+ *
238
+ * holdings is read from the chain and is not money Stable Sea holds. See the listing for what each holdings_status means.
239
+ *
240
+ * SCOPING. Any wallet this credential's business has connected may be retrieved, and nothing else. An id that names no wallet, one belonging to another business, and one whose wallet has been removed are answered identically.
241
+ */
242
+ get: operations["external_wallets.get"];
243
+ put?: never;
244
+ post?: never;
245
+ delete?: never;
246
+ options?: never;
247
+ head?: never;
248
+ patch?: never;
249
+ trace?: never;
250
+ };
251
+ "/v1/notifications": {
252
+ parameters: {
253
+ query?: never;
254
+ header?: never;
255
+ path?: never;
256
+ cookie?: never;
257
+ };
258
+ /**
259
+ * List notifications
260
+ * @description Lists eligible business-wide notices newest first after a 60-second stability window. Personal, integration, and bell seen-state notifications are excluded. A locked business cannot read the feed. A test credential cannot read live notices.
261
+ */
262
+ get: operations["notifications.list"];
263
+ put?: never;
264
+ post?: never;
265
+ delete?: never;
266
+ options?: never;
267
+ head?: never;
268
+ patch?: never;
269
+ trace?: never;
270
+ };
271
+ "/v1/notifications/{id}": {
272
+ parameters: {
273
+ query?: never;
274
+ header?: never;
275
+ path?: never;
276
+ cookie?: never;
277
+ };
278
+ /**
279
+ * Retrieve a notification
280
+ * @description Returns one eligible business-wide notice by id. Other businesses' and excluded notices are indistinguishable from unknown ids. A test credential cannot read live notices. Notifications already announced in the credential environment remain retrievable after a ledger-mode cutover.
281
+ */
282
+ get: operations["notifications.retrieve"];
283
+ put?: never;
284
+ post?: never;
285
+ delete?: never;
286
+ options?: never;
287
+ head?: never;
288
+ patch?: never;
289
+ trace?: never;
290
+ };
199
291
  "/v1/orders": {
200
292
  parameters: {
201
293
  query?: never;
@@ -244,6 +336,26 @@ export interface paths {
244
336
  patch?: never;
245
337
  trace?: never;
246
338
  };
339
+ "/v1/policies": {
340
+ parameters: {
341
+ query?: never;
342
+ header?: never;
343
+ path?: never;
344
+ cookie?: never;
345
+ };
346
+ /**
347
+ * Read effective money controls
348
+ * @description Read the authenticated business's movement switches, effective calendar/rolling limits and outgoing approval tiers. No policy or financial writes. These are current observations, not a transfer authorization. No withdrawal endpoint is enabled by this read. Delay/cooloff report supported=false; null limits mean no flow-wide cap, not unavailable data. Highest matching approval minimum applies when USD valuation is known. If USD valuation is unavailable for an on-chain withdrawal or fund trade, the highest configured approval rule for that flow applies regardless of amount. Changed pending policies require resubmission.
349
+ */
350
+ get: operations["policies.snapshot"];
351
+ put?: never;
352
+ post?: never;
353
+ delete?: never;
354
+ options?: never;
355
+ head?: never;
356
+ patch?: never;
357
+ trace?: never;
358
+ };
247
359
  "/v1/quotes": {
248
360
  parameters: {
249
361
  query?: never;
@@ -328,6 +440,26 @@ export interface paths {
328
440
  patch?: never;
329
441
  trace?: never;
330
442
  };
443
+ "/v1/statements/{id}/content": {
444
+ parameters: {
445
+ query?: never;
446
+ header?: never;
447
+ path?: never;
448
+ cookie?: never;
449
+ };
450
+ /**
451
+ * Retrieve statement content
452
+ * @description Returns the immutable issued statement values as display-ready JSON. Corrected statements remain retrievable and name their replacement. Pay-ins and payouts are not served on this API, so they are not listed in transactions; the balances and totals are the printed ones and still include their effect, which means a statement for a period in which the business made a payment does not reconcile from its transactions alone.
453
+ */
454
+ get: operations["statements.content.retrieve"];
455
+ put?: never;
456
+ post?: never;
457
+ delete?: never;
458
+ options?: never;
459
+ head?: never;
460
+ patch?: never;
461
+ trace?: never;
462
+ };
331
463
  "/v1/transactions": {
332
464
  parameters: {
333
465
  query?: never;
@@ -339,11 +471,13 @@ export interface paths {
339
471
  * List transactions
340
472
  * @description Lists the business's money movements, newest first.
341
473
  *
342
- * SCOPING. The response covers every movement booked for this credential's business, so one cursor sweep reconciles everything. There is no narrower scope to ask for: one credential addresses one business.
474
+ * SCOPING. The response covers every movement booked for this credential's business except the pay-ins and payouts described below, so one cursor sweep reconciles everything this API serves. There is no narrower scope to ask for: one credential addresses one business.
475
+ *
476
+ * WHAT A ROW IS. One row is one MOVEMENT — the whole operation, not its ledger legs. asset_changes carries its signed net effect on the business's own holdings, one entry per asset: negative left, positive arrived. Amounts are net of the ledger's fees and taxes, on the same basis /v1/balances reports. Legs that touch accounts /v1/balances does not report are left out — a bank account, a whitelisted withdrawal address — and so are legs that failed, which never reached a balance.
343
477
  *
344
- * WHAT A ROW IS. One row is one MOVEMENT — the whole operation, not its ledger legs. asset_changes carries its signed net effect on the business's own holdings, one entry per asset: negative left, positive arrived. Amounts are net of the ledger's fees and taxes, on the same basis /v1/balances reports. Legs that touch accounts /v1/balances does not report are left out — a payout's beneficiary side, a bank account, a whitelisted withdrawal address — and so are legs that failed, which never reached a balance.
478
+ * PAY-INS AND PAYOUTS ARE NOT SERVED. This API never lists a pay-in or a payout — not as a row here, not as a statement entry, not as an event — for any business, whatever its Payments settings say. Payments are managed in the dashboard, not on this API.
345
479
  *
346
- * RECONCILING AGAINST /v1/balances. Sum an asset's amounts across EVERY transaction, with no filter on status, and the total is the movement in that asset's settled balance. Do not restrict the sum to completed transactions: asset_changes reports what has SETTLED, which is not the same fact as the movement's status. A movement whose legs are still in flight reports no change at all, even one already marked processing; a movement that FAILED after part of it settled reports the part that settled, because that money really moved.
480
+ * RECONCILING AGAINST /v1/balances. For a business with no pay-ins or payouts, sum an asset's amounts across EVERY transaction, with no filter on status, and the total is the movement in that asset's settled balance. Do not restrict the sum to completed transactions: asset_changes reports what has SETTLED, which is not the same fact as the movement's status. A movement whose legs are still in flight reports no change at all, even one already marked processing; a movement that FAILED after part of it settled reports the part that settled, because that money really moved. THE EXCEPTION IS PAYMENTS: /v1/balances and a statement's totals still include the effect of a pay-in or payout, but this listing does not serve the movement. A business with payment movements therefore cannot reconcile its balance from /v1/transactions alone — the transactions sum short by exactly its payments.
347
481
  *
348
482
  * STATUS. pending means no leg has been picked up yet. processing means at least one leg is in flight. completed means every leg settled, and completed_ts is the instant the last one did. failed means the movement terminated without settling, and failed_ts is when. The two non-terminal states are reported separately because they call for opposite responses: a movement nothing has touched may be worth chasing, one already in flight must be left alone.
349
483
  *
@@ -377,7 +511,7 @@ export interface paths {
377
511
  *
378
512
  * FIGURES. asset_changes is the signed net effect on the business's OWN SETTLED holdings, one entry per asset: negative left, positive arrived. Amounts are net of the ledger's fees and taxes, on the same basis /v1/balances reports. Legs touching accounts /v1/balances does not report are left out, and so are legs that failed — a failed leg never reached a balance.
379
513
  *
380
- * IT REPORTS WHAT SETTLED, NOT WHAT THE STATUS SAYS. A movement still in flight reports no change at all, because none of its legs has reached a balance yet. A movement that failed after part of it settled reports the part that settled. One whose every leg failed reports no change. Sum an asset's amounts across every transaction — with no filter on status — to reconcile against /v1/balances.
514
+ * IT REPORTS WHAT SETTLED, NOT WHAT THE STATUS SAYS. A movement still in flight reports no change at all, because none of its legs has reached a balance yet. A movement that failed after part of it settled reports the part that settled. One whose every leg failed reports no change. For a business with no pay-ins or payouts, sum an asset's amounts across every transaction — with no filter on status — to reconcile against /v1/balances. Pay-ins and payouts are never served on this API, though /v1/balances still includes their effect, so a business with payment movements cannot reconcile its balance from /v1/transactions alone.
381
515
  *
382
516
  * STATUS. The four states are pending, processing, completed and failed. completed_ts and failed_ts are mutually exclusive, and neither is present while the movement is in flight.
383
517
  *
@@ -449,7 +583,7 @@ export interface paths {
449
583
  };
450
584
  /**
451
585
  * List webhook deliveries
452
- * @description Lists secret-free delivery health for an endpoint, newest first. limit defaults to 10 and may not exceed 100. starting_after and ending_before are mutually exclusive.
586
+ * @description Lists secret-free delivery health for an endpoint, newest first. limit defaults to 10 and may not exceed 100. starting_after and ending_before are mutually exclusive. Deliveries of events about pay-ins and payouts (and held deposits, which have no /v1 transaction) are not served, and none is sent. A cursor that names a withheld delivery is refused like a cursor that names no delivery, so restart from the newest page by sending no cursor.
453
587
  */
454
588
  get: operations["webhook_deliveries.list"];
455
589
  put?: never;
@@ -469,7 +603,7 @@ export interface paths {
469
603
  };
470
604
  /**
471
605
  * Retrieve a webhook delivery
472
- * @description Retrieves delivery health for one endpoint and event.
606
+ * @description Retrieves delivery health for one endpoint and event. Deliveries of events about pay-ins and payouts (and held deposits, which have no /v1 transaction) are not served, and none is sent. Asking for one is answered like an id that names no delivery.
473
607
  */
474
608
  get: operations["webhook_deliveries.get"];
475
609
  put?: never;
@@ -491,7 +625,7 @@ export interface paths {
491
625
  put?: never;
492
626
  /**
493
627
  * Replay a webhook delivery
494
- * @description Requeues one dead webhook delivery using its original event and endpoint revision, with a new three-day retry window.
628
+ * @description Requeues one dead webhook delivery using its original event and endpoint revision, with a new three-day retry window. Deliveries of events about pay-ins and payouts (and held deposits, which have no /v1 transaction) are not served, and none is sent. Asking to replay one is answered like an id that names no delivery, and nothing is requeued.
495
629
  */
496
630
  post: operations["webhook_deliveries.replay"];
497
631
  delete?: never;
@@ -588,7 +722,7 @@ export interface components {
588
722
  * @description The network this holding sits on. off_chain is the chain-agnostic omnibus balance; unknown means the chain could not be attributed, and the holding is reported anyway rather than dropped.
589
723
  * @enum {string}
590
724
  */
591
- chain: "off_chain" | "ethereum" | "arbitrum" | "base" | "stellar" | "unknown";
725
+ chain: "off_chain" | "ethereum" | "arbitrum" | "base" | "stellar" | "solana" | "unknown";
592
726
  /**
593
727
  * Format: date-time
594
728
  * @description The instant the ledger was cut and the assets were priced. Every figure below is as of this instant.
@@ -596,7 +730,7 @@ export interface components {
596
730
  created_ts: string;
597
731
  /** @description The balance id. Derived from (business, chain, source, asset, segregated rail), so it is stable across reads and safe to diff against. */
598
732
  id: string;
599
- /** @description Always true. A balance is a fact about real custodied money; there is no test ledger. */
733
+ /** @description False only for an isolated mock-money-only ledger; independent of the reading credential. */
600
734
  livemode: boolean;
601
735
  /** @enum {string} */
602
736
  object: "balance";
@@ -686,7 +820,69 @@ export interface components {
686
820
  object: "list";
687
821
  };
688
822
  /** @enum {string} */
689
- EventTypeName: "order.updated" | "transaction.created" | "transaction.updated";
823
+ EventTypeName: "notification.created" | "order.updated" | "transaction.created" | "transaction.updated";
824
+ ExternalWallet: {
825
+ /** @description The wallet's on-chain address, exactly as the business connected it. */
826
+ address: string;
827
+ /**
828
+ * Format: date-time
829
+ * @description When the wallet was connected. The list is ordered and paged on this instant.
830
+ */
831
+ created_ts: string;
832
+ /**
833
+ * Format: uri
834
+ * @description The address's page on a public block explorer. Absent when the network has none.
835
+ */
836
+ explorer_url?: string;
837
+ /** @description The wallet's non-zero holdings of the tokens Stable Sea tracks, read from the chain. Only populated when holdings_status is ok or stale; an ok reading with no entries means the wallet holds none of those tokens. These are not funds Stable Sea holds, and they are never part of /v1/balances. */
838
+ holdings: components["schemas"]["ExternalWalletHolding"][];
839
+ /**
840
+ * Format: date-time
841
+ * @description When holdings was read from the chain. Present only when holdings_status is ok or stale.
842
+ */
843
+ holdings_read_ts?: string;
844
+ /**
845
+ * @description Whether holdings carries a reading. ok: the latest read succeeded. stale: the latest read failed, and holdings is the last good read. Either way holdings_read_ts says when it was read, and it is at most 15 minutes old. unavailable: no good read within 15 minutes; holdings is empty, which says nothing about what the wallet holds. shared_address: a Stellar address with a memo, which holds other people's funds and is never read. not_monitored: the wallet's holdings are not read, because it is disabled, on a network we do not monitor, or not yet cleared for withdrawals.
846
+ * @enum {string}
847
+ */
848
+ holdings_status: "ok" | "stale" | "unavailable" | "shared_address" | "not_monitored";
849
+ /** @description The external wallet id. Stable for the life of the wallet and safe to store. */
850
+ id: string;
851
+ /** @description False only under the validated mock-money-only profile; independent of the reading credential. */
852
+ livemode: boolean;
853
+ /** @description The Stellar memo the business attached to the address. Absent when there is none. A wallet with a memo is a shared deposit address, such as an exchange's, and its holdings are never read. */
854
+ memo?: string;
855
+ /** @enum {string} */
856
+ object: "external_wallet";
857
+ /** @description The network the wallet is on, as a withdrawal rail (onchain_ethereum, onchain_stellar). */
858
+ payment_rail: string;
859
+ /**
860
+ * @description enabled: the business has the wallet switched on as a withdrawal destination (a withdrawal to it can still be held for review). disabled: the business switched it off, and withdrawals to it are refused until it is enabled again.
861
+ * @enum {string}
862
+ */
863
+ status: "enabled" | "disabled";
864
+ };
865
+ ExternalWalletHolding: {
866
+ /** @description The quantity held, in the token's own units. Exact, never rounded, and always above zero. */
867
+ amount: string;
868
+ /** @description The token's on-chain identity: the ERC-20 contract address on Ethereum, CODE:ISSUER on Stellar. Two tokens can share a symbol; this cannot. */
869
+ asset_ref: string;
870
+ /** @description The token's symbol (USDC, WTGXX). */
871
+ symbol: string;
872
+ /** @description The holding valued in USD, to the cent. null when valuation_basis is none: a token we do not value carries no dollar figure rather than a zero. */
873
+ usd_value: string | null;
874
+ /**
875
+ * @description How usd_value was reached. pegged: valued at 1.00 USD per unit, the fixed value Stable Sea's own ledger gives this asset. assumed_par: a USD stablecoin Stable Sea does not price, valued at 1.00 USD per unit by assumption. none: no price source, so not valued. usd_value is for display and is never part of a Stable Sea balance.
876
+ * @enum {string}
877
+ */
878
+ valuation_basis: "pegged" | "assumed_par" | "none";
879
+ };
880
+ ExternalWalletList: {
881
+ data: components["schemas"]["ExternalWallet"][];
882
+ has_more: boolean;
883
+ /** @enum {string} */
884
+ object: "list";
885
+ };
690
886
  List: {
691
887
  data: components["schemas"]["Resource"][];
692
888
  has_more: boolean;
@@ -697,6 +893,32 @@ export interface components {
697
893
  Metadata: {
698
894
  [key: string]: string;
699
895
  };
896
+ Notification: {
897
+ /** Format: date-time */
898
+ created_ts: string;
899
+ id: string;
900
+ livemode: boolean;
901
+ /** @enum {string} */
902
+ object: "notification";
903
+ resource?: {
904
+ id: string;
905
+ /** @enum {string} */
906
+ object: "statement";
907
+ };
908
+ /** @enum {string} */
909
+ type: "balance_statement_ready" | "payout_destination_changed" | "account_frozen" | "deposit_refused_embargo";
910
+ };
911
+ NotificationList: {
912
+ data: components["schemas"]["Notification"][];
913
+ has_more: boolean;
914
+ /** @enum {string} */
915
+ object: "list";
916
+ };
917
+ NotificationResource: {
918
+ id: string;
919
+ /** @enum {string} */
920
+ object: "statement";
921
+ };
700
922
  Order: {
701
923
  amount: string;
702
924
  /** Format: date-time */
@@ -740,6 +962,112 @@ export interface components {
740
962
  /** @enum {string} */
741
963
  object: "list";
742
964
  };
965
+ Policy: {
966
+ /** @description If USD valuation is unavailable for an on-chain withdrawal or fund trade, the highest configured approval rule for that flow applies regardless of amount. */
967
+ approval_tiers: components["schemas"]["PolicyApprovalTier"][];
968
+ /** @description The business's movement switch; not a guarantee that identity, compliance, asset or partner checks will permit execution. */
969
+ enabled: boolean;
970
+ limits: components["schemas"]["PolicyLimits"];
971
+ new_destination_cooloff: {
972
+ /** @description False: this control has not been implemented. */
973
+ supported: boolean;
974
+ };
975
+ /** @enum {string} */
976
+ object: "policy";
977
+ rail: string;
978
+ release_delay: {
979
+ /** @description False: this control has not been implemented. */
980
+ supported: boolean;
981
+ };
982
+ };
983
+ /** @enum {string} */
984
+ PolicyApprovalFlow: "ach_withdrawal" | "wire_withdrawal" | "onchain_withdrawal" | "fund_buy" | "fund_sell";
985
+ PolicyApprovalTier: {
986
+ /** Format: int32 */
987
+ approvals_required: number;
988
+ /** @enum {string} */
989
+ flow: "ach_withdrawal" | "wire_withdrawal" | "onchain_withdrawal" | "fund_buy" | "fund_sell";
990
+ /** @description Legacy thresholds may require strictly greater than min_usd; current rules are inclusive. */
991
+ min_inclusive: boolean;
992
+ min_usd: string;
993
+ /** @description An additional named approval is required. Ordinary counts exclude both requester and named approver. */
994
+ named_approval_required: boolean;
995
+ };
996
+ PolicyDelay: {
997
+ /** @description False: this control has not been implemented. */
998
+ supported: boolean;
999
+ };
1000
+ /** @enum {string} */
1001
+ PolicyLimitScope: "all_assets" | "par_usd_assets";
1002
+ PolicyLimits: {
1003
+ daily: {
1004
+ /** @enum {string} */
1005
+ applies_to: "all_assets" | "par_usd_assets";
1006
+ limit_usd: string;
1007
+ remaining_usd: string;
1008
+ /**
1009
+ * Format: int64
1010
+ * @description Movements omitted from the USD-valued used figure because no rate was available.
1011
+ */
1012
+ unpriced_movements: number;
1013
+ used_usd: string;
1014
+ /** @enum {string} */
1015
+ window: "calendar_day" | "calendar_week" | "rolling_24h" | "rolling_72h";
1016
+ } | null;
1017
+ /** @description Null means there is no flow-wide per-transaction USD cap. Asset and settlement-pathway gates still apply. */
1018
+ per_transaction: {
1019
+ /** @enum {string} */
1020
+ applies_to: "all_assets" | "par_usd_assets";
1021
+ limit_usd: string;
1022
+ remaining_usd: string;
1023
+ /**
1024
+ * Format: int64
1025
+ * @description Movements omitted from the USD-valued used figure because no rate was available.
1026
+ */
1027
+ unpriced_movements: number;
1028
+ used_usd: string;
1029
+ /** @enum {string} */
1030
+ window: "calendar_day" | "calendar_week" | "rolling_24h" | "rolling_72h";
1031
+ } | null;
1032
+ rolling: {
1033
+ /** @enum {string} */
1034
+ applies_to: "all_assets" | "par_usd_assets";
1035
+ limit_usd: string;
1036
+ remaining_usd: string;
1037
+ /**
1038
+ * Format: int64
1039
+ * @description Movements omitted from the USD-valued used figure because no rate was available.
1040
+ */
1041
+ unpriced_movements: number;
1042
+ used_usd: string;
1043
+ /** @enum {string} */
1044
+ window: "calendar_day" | "calendar_week" | "rolling_24h" | "rolling_72h";
1045
+ } | null;
1046
+ weekly: {
1047
+ /** @enum {string} */
1048
+ applies_to: "all_assets" | "par_usd_assets";
1049
+ limit_usd: string;
1050
+ remaining_usd: string;
1051
+ /**
1052
+ * Format: int64
1053
+ * @description Movements omitted from the USD-valued used figure because no rate was available.
1054
+ */
1055
+ unpriced_movements: number;
1056
+ used_usd: string;
1057
+ /** @enum {string} */
1058
+ window: "calendar_day" | "calendar_week" | "rolling_24h" | "rolling_72h";
1059
+ } | null;
1060
+ };
1061
+ PolicySnapshot: {
1062
+ data: components["schemas"]["Policy"][];
1063
+ livemode: boolean;
1064
+ /** @enum {string} */
1065
+ object: "policy_snapshot";
1066
+ /** Format: date-time */
1067
+ observed_ts: string;
1068
+ };
1069
+ /** @enum {string} */
1070
+ PolicyWindowKind: "calendar_day" | "calendar_week" | "rolling_24h" | "rolling_72h";
743
1071
  Quote: {
744
1072
  amount_usd: string;
745
1073
  /** @enum {string} */
@@ -815,12 +1143,105 @@ export interface components {
815
1143
  period_start_ts: string;
816
1144
  superseded_by?: string;
817
1145
  };
1146
+ StatementCommission: {
1147
+ amount: string;
1148
+ label: string;
1149
+ symbol: string;
1150
+ };
1151
+ StatementContent: {
1152
+ balances: components["schemas"]["StatementLine"][];
1153
+ /** Format: date-time */
1154
+ created_ts: string;
1155
+ id: string;
1156
+ livemode: boolean;
1157
+ /** @enum {string} */
1158
+ object: "statement_content";
1159
+ period: components["schemas"]["StatementPeriod"];
1160
+ ramp_fees?: components["schemas"]["StatementRampFee"][];
1161
+ superseded_by?: string;
1162
+ totals: components["schemas"]["StatementTotals"];
1163
+ /** @description The period's movements. Pay-ins and payouts are never served on this API, so they are not listed here although balances and totals include their effect: for a period in which the business made a payment the entries do not sum to the totals. */
1164
+ transactions: components["schemas"]["StatementEntry"][];
1165
+ };
1166
+ StatementEffect: {
1167
+ amount: string;
1168
+ /** @enum {string} */
1169
+ amount_status?: "provisional" | "settled";
1170
+ quoted_amount?: string;
1171
+ symbol: string;
1172
+ };
1173
+ StatementEntry: {
1174
+ commission?: components["schemas"]["StatementCommission"];
1175
+ effects: components["schemas"]["StatementEffect"][];
1176
+ id: string;
1177
+ label: string;
1178
+ /** Format: date-time */
1179
+ occurred_ts: string;
1180
+ /** @enum {string} */
1181
+ status: "completed" | "pending" | "failed";
1182
+ /** @enum {string} */
1183
+ type: "ach_offramp" | "ach_onramp" | "adjustment" | "buy_fund_token" | "buy_fund_token_return" | "buy_fund_token_return_sweep" | "deposit_hold" | "deposit_return" | "deposit_reversal" | "fund_cash_subscription" | "fund_dividend_payout" | "fund_distribution_payout" | "fund_gas_tank" | "fund_xlm_reserve" | "gas_tank_refill" | "gas_wallet_funding" | "go_account_conversion" | "go_account_custodial_transfer" | "go_account_external_send" | "held_deposit_release" | "onchain_deposit" | "onchain_withdrawal" | "ramp_fee_refund" | "reclassification" | "sell_fund_token" | "sell_fund_token_return" | "trade_order" | "treasury_booking" | "treasury_wire_credit" | "wire_offramp" | "wire_onramp";
1184
+ withdrawal?: components["schemas"]["StatementWithdrawal"];
1185
+ };
1186
+ StatementLine: {
1187
+ ending_native: string;
1188
+ ending_usd: string;
1189
+ label: string;
1190
+ net_change_native: string;
1191
+ net_change_usd: string;
1192
+ opening_native: string;
1193
+ opening_usd: string;
1194
+ segregated_rail?: string;
1195
+ symbol: string;
1196
+ };
818
1197
  StatementList: {
819
1198
  data: components["schemas"]["Statement"][];
820
1199
  has_more: boolean;
821
1200
  /** @enum {string} */
822
1201
  object: "list";
823
1202
  };
1203
+ StatementPeriod: {
1204
+ /** Format: date-time */
1205
+ end_ts: string;
1206
+ label: string;
1207
+ /** Format: date-time */
1208
+ start_ts: string;
1209
+ };
1210
+ StatementRampFee: {
1211
+ /** Format: date-time */
1212
+ assessed_ts: string;
1213
+ assessed_usdc: string;
1214
+ bank_fee_usd: string;
1215
+ collected_usdc: string;
1216
+ /** @enum {string} */
1217
+ direction: "onramp" | "offramp";
1218
+ events: components["schemas"]["StatementRampFeeEvent"][];
1219
+ net_proceeds_usdc?: string;
1220
+ paid_to_bank_usd?: string;
1221
+ principal_usd: string;
1222
+ refunded_usdc: string;
1223
+ /** @enum {string} */
1224
+ status: "not_needed" | "pending" | "collected" | "waived" | "partially_refunded" | "refunded";
1225
+ total_debit_usdc?: string;
1226
+ transaction_id: string;
1227
+ };
1228
+ StatementRampFeeEvent: {
1229
+ amount_usdc: string;
1230
+ /** @enum {string} */
1231
+ kind: "collection" | "refund";
1232
+ /** Format: date-time */
1233
+ settled_ts: string;
1234
+ transaction_id: string;
1235
+ };
1236
+ StatementTotals: {
1237
+ ending_usd: string;
1238
+ net_change_usd: string;
1239
+ opening_usd: string;
1240
+ };
1241
+ StatementWithdrawal: {
1242
+ fee: string;
1243
+ paid_to_bank: string;
1244
+ };
824
1245
  Transaction: {
825
1246
  /** @description The signed net change to the business's own SETTLED holdings, one entry per asset, ordered by asset. Empty when nothing of the business's own has settled yet: a movement still pending or processing reports no change, and neither does one whose every leg failed. A failed movement DOES report the legs that settled before it failed. */
826
1247
  asset_changes: components["schemas"]["TransactionAssetChange"][];
@@ -841,7 +1262,7 @@ export interface components {
841
1262
  failed_ts?: string;
842
1263
  /** @description The transaction id. Stable for the life of the movement and safe to store. */
843
1264
  id: string;
844
- /** @description Always true. A transaction records real custodied money moving; there is no test ledger. */
1265
+ /** @description False only for an isolated mock-money-only ledger; independent of the reading credential. */
845
1266
  livemode: boolean;
846
1267
  /** @enum {string} */
847
1268
  object: "transaction";
@@ -851,13 +1272,13 @@ export interface components {
851
1272
  */
852
1273
  status: "pending" | "processing" | "completed" | "failed";
853
1274
  /**
854
- * @description What the movement is. The full vocabulary is published; a business only ever sees the members its own activity produces.
1275
+ * @description What the movement is. The whole vocabulary a transaction can carry is published; a business only ever sees the members its own activity produces. Pay-ins and payouts are never served on this API.
855
1276
  * @enum {string}
856
1277
  */
857
- type: "ach_offramp" | "ach_onramp" | "adjustment" | "bank_payin" | "bank_payout" | "buy_fund_token" | "buy_fund_token_return" | "fund_cash_subscription" | "fund_dividend_payout" | "fund_distribution_payout" | "fund_gas_tank" | "fund_xlm_reserve" | "gas_wallet_funding" | "go_account_conversion" | "go_account_custodial_transfer" | "go_account_external_send" | "onchain_deposit" | "onchain_withdrawal" | "reclassification" | "sell_fund_token" | "sell_fund_token_return" | "trade_order" | "treasury_booking" | "treasury_wire_credit" | "wire_offramp" | "wire_onramp";
1278
+ type: "ach_offramp" | "ach_onramp" | "adjustment" | "buy_fund_token" | "buy_fund_token_return" | "buy_fund_token_return_sweep" | "deposit_hold" | "deposit_return" | "deposit_reversal" | "fund_cash_subscription" | "fund_dividend_payout" | "fund_distribution_payout" | "fund_gas_tank" | "fund_xlm_reserve" | "gas_tank_refill" | "gas_wallet_funding" | "go_account_conversion" | "go_account_custodial_transfer" | "go_account_external_send" | "held_deposit_release" | "onchain_deposit" | "onchain_withdrawal" | "ramp_fee_refund" | "reclassification" | "sell_fund_token" | "sell_fund_token_return" | "trade_order" | "treasury_booking" | "treasury_wire_credit" | "wire_offramp" | "wire_onramp";
858
1279
  };
859
1280
  TransactionAssetChange: {
860
- /** @description The signed net change to the business's settled holdings of this asset, in the asset's own units. NEGATIVE LEFT the business, positive arrived. Net of the ledger's fees and taxes, on the same basis /v1/balances reports. Summing an asset's amounts across every transaction — not only the completed ones — gives the movement in its settled balance. */
1281
+ /** @description The signed net change to the business's settled holdings of this asset, in the asset's own units. NEGATIVE LEFT the business, positive arrived. Net of the ledger's fees and taxes, on the same basis /v1/balances reports. For a business with no pay-ins or payouts, summing an asset's amounts across every transaction — not only the completed ones — gives the movement in its settled balance. Pay-ins and payouts are not served on this API but still move /v1/balances, so a business with payments cannot reconcile its balance from transactions alone. */
861
1282
  amount: string;
862
1283
  /** @description The asset symbol, in the ledger's own casing (USDC, WTGXX, SOL:USDC). */
863
1284
  asset: string;
@@ -1236,6 +1657,142 @@ export interface operations {
1236
1657
  };
1237
1658
  };
1238
1659
  };
1660
+ "external_wallets.list": {
1661
+ parameters: {
1662
+ query?: {
1663
+ /** @description How many external wallets to return. Defaults to 10. A value above 100 is rejected, not reduced. */
1664
+ limit?: number;
1665
+ /** @description Return the external wallets immediately after this external wallet id in the list order. Cannot be combined with ending_before. */
1666
+ starting_after?: string;
1667
+ /** @description Return the external wallets immediately before this external wallet id in the list order. Cannot be combined with starting_after. */
1668
+ ending_before?: string;
1669
+ };
1670
+ header?: never;
1671
+ path?: never;
1672
+ cookie?: never;
1673
+ };
1674
+ requestBody?: never;
1675
+ responses: {
1676
+ /** @description OK */
1677
+ 200: {
1678
+ headers: {
1679
+ [name: string]: unknown;
1680
+ };
1681
+ content: {
1682
+ "application/json": components["schemas"]["ExternalWalletList"];
1683
+ };
1684
+ };
1685
+ /** @description Error response. */
1686
+ default: {
1687
+ headers: {
1688
+ [name: string]: unknown;
1689
+ };
1690
+ content: {
1691
+ "application/json": components["schemas"]["Error"];
1692
+ };
1693
+ };
1694
+ };
1695
+ };
1696
+ "external_wallets.get": {
1697
+ parameters: {
1698
+ query?: never;
1699
+ header?: never;
1700
+ path: {
1701
+ /** @description The external wallet id. */
1702
+ id: string;
1703
+ };
1704
+ cookie?: never;
1705
+ };
1706
+ requestBody?: never;
1707
+ responses: {
1708
+ /** @description OK */
1709
+ 200: {
1710
+ headers: {
1711
+ [name: string]: unknown;
1712
+ };
1713
+ content: {
1714
+ "application/json": components["schemas"]["ExternalWallet"];
1715
+ };
1716
+ };
1717
+ /** @description Error response. */
1718
+ default: {
1719
+ headers: {
1720
+ [name: string]: unknown;
1721
+ };
1722
+ content: {
1723
+ "application/json": components["schemas"]["Error"];
1724
+ };
1725
+ };
1726
+ };
1727
+ };
1728
+ "notifications.list": {
1729
+ parameters: {
1730
+ query?: {
1731
+ /** @description How many notifications to return. Defaults to 10. */
1732
+ limit?: number;
1733
+ /** @description Return the notifications immediately older than this notification id. Cannot be combined with ending_before. */
1734
+ starting_after?: string;
1735
+ /** @description Return the notifications immediately newer than this notification id. Cannot be combined with starting_after. */
1736
+ ending_before?: string;
1737
+ };
1738
+ header?: never;
1739
+ path?: never;
1740
+ cookie?: never;
1741
+ };
1742
+ requestBody?: never;
1743
+ responses: {
1744
+ /** @description OK */
1745
+ 200: {
1746
+ headers: {
1747
+ [name: string]: unknown;
1748
+ };
1749
+ content: {
1750
+ "application/json": components["schemas"]["NotificationList"];
1751
+ };
1752
+ };
1753
+ /** @description Error response. */
1754
+ default: {
1755
+ headers: {
1756
+ [name: string]: unknown;
1757
+ };
1758
+ content: {
1759
+ "application/json": components["schemas"]["Error"];
1760
+ };
1761
+ };
1762
+ };
1763
+ };
1764
+ "notifications.retrieve": {
1765
+ parameters: {
1766
+ query?: never;
1767
+ header?: never;
1768
+ path: {
1769
+ /** @description The notification id. */
1770
+ id: string;
1771
+ };
1772
+ cookie?: never;
1773
+ };
1774
+ requestBody?: never;
1775
+ responses: {
1776
+ /** @description OK */
1777
+ 200: {
1778
+ headers: {
1779
+ [name: string]: unknown;
1780
+ };
1781
+ content: {
1782
+ "application/json": components["schemas"]["Notification"];
1783
+ };
1784
+ };
1785
+ /** @description Error response. */
1786
+ default: {
1787
+ headers: {
1788
+ [name: string]: unknown;
1789
+ };
1790
+ content: {
1791
+ "application/json": components["schemas"]["Error"];
1792
+ };
1793
+ };
1794
+ };
1795
+ };
1239
1796
  "orders.list": {
1240
1797
  parameters: {
1241
1798
  query?: {
@@ -1339,6 +1896,35 @@ export interface operations {
1339
1896
  };
1340
1897
  };
1341
1898
  };
1899
+ "policies.snapshot": {
1900
+ parameters: {
1901
+ query?: never;
1902
+ header?: never;
1903
+ path?: never;
1904
+ cookie?: never;
1905
+ };
1906
+ requestBody?: never;
1907
+ responses: {
1908
+ /** @description OK */
1909
+ 200: {
1910
+ headers: {
1911
+ [name: string]: unknown;
1912
+ };
1913
+ content: {
1914
+ "application/json": components["schemas"]["PolicySnapshot"];
1915
+ };
1916
+ };
1917
+ /** @description Error response. */
1918
+ default: {
1919
+ headers: {
1920
+ [name: string]: unknown;
1921
+ };
1922
+ content: {
1923
+ "application/json": components["schemas"]["Error"];
1924
+ };
1925
+ };
1926
+ };
1927
+ };
1342
1928
  "quotes.quote": {
1343
1929
  parameters: {
1344
1930
  query: {
@@ -1472,6 +2058,38 @@ export interface operations {
1472
2058
  };
1473
2059
  };
1474
2060
  };
2061
+ "statements.content.retrieve": {
2062
+ parameters: {
2063
+ query?: never;
2064
+ header?: never;
2065
+ path: {
2066
+ /** @description The statement id. */
2067
+ id: string;
2068
+ };
2069
+ cookie?: never;
2070
+ };
2071
+ requestBody?: never;
2072
+ responses: {
2073
+ /** @description OK */
2074
+ 200: {
2075
+ headers: {
2076
+ [name: string]: unknown;
2077
+ };
2078
+ content: {
2079
+ "application/json": components["schemas"]["StatementContent"];
2080
+ };
2081
+ };
2082
+ /** @description Error response. */
2083
+ default: {
2084
+ headers: {
2085
+ [name: string]: unknown;
2086
+ };
2087
+ content: {
2088
+ "application/json": components["schemas"]["Error"];
2089
+ };
2090
+ };
2091
+ };
2092
+ };
1475
2093
  "transactions.list": {
1476
2094
  parameters: {
1477
2095
  query?: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stable_sea/sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "files": [
@@ -35,13 +35,14 @@
35
35
  "openapi-fetch": "0.17.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@types/node": "24.10.1",
38
+ "@types/node": "26.6.3",
39
39
  "openapi-typescript": "7.13.0",
40
40
  "typescript": "5.9.3",
41
- "vitest": "4.1.11"
41
+ "vitest": "5.0.2"
42
42
  },
43
43
  "overrides": {
44
- "js-yaml": "^5.4.1",
45
- "nanoid": "^3.3.17"
44
+ "js-yaml": "^5.4.2",
45
+ "nanoid": "^3.3.17",
46
+ "source-map-js": "^1.2.2"
46
47
  }
47
48
  }