@coinlist-co/react 0.5.1 → 0.9.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/dist/{chunk-5E3P7AMH.js → chunk-AAER5LOL.js} +3 -1
- package/dist/chunk-AAER5LOL.js.map +1 -0
- package/dist/chunk-I5YTJ5SL.js +644 -0
- package/dist/chunk-I5YTJ5SL.js.map +1 -0
- package/dist/{chunk-N3WBC2VS.js → chunk-MKCOK3DF.js} +68 -57
- package/dist/chunk-MKCOK3DF.js.map +1 -0
- package/dist/chunk-Z2HAA2TI.js +768 -0
- package/dist/chunk-Z2HAA2TI.js.map +1 -0
- package/dist/client/index.cjs +3360 -556
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +921 -18
- package/dist/client/index.d.ts +921 -18
- package/dist/client/index.js +2275 -392
- package/dist/client/index.js.map +1 -1
- package/dist/collections-B84Vw55t.d.cts +28 -0
- package/dist/collections-BQbFJS3g.d.ts +28 -0
- package/dist/requirement-C2w45Q11.d.cts +969 -0
- package/dist/requirement-C2w45Q11.d.ts +969 -0
- package/dist/server/index.cjs +521 -37
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +116 -9
- package/dist/server/index.d.ts +116 -9
- package/dist/server/index.js +95 -28
- package/dist/server/index.js.map +1 -1
- package/dist/shared/index.cjs +1264 -42
- package/dist/shared/index.cjs.map +1 -1
- package/dist/shared/index.d.cts +644 -3
- package/dist/shared/index.d.ts +644 -3
- package/dist/shared/index.js +220 -5
- package/dist/shared/index.js.map +1 -1
- package/package.json +33 -30
- package/dist/chunk-5E3P7AMH.js.map +0 -1
- package/dist/chunk-CRACFEJ4.js +0 -17
- package/dist/chunk-CRACFEJ4.js.map +0 -1
- package/dist/chunk-N3WBC2VS.js.map +0 -1
- package/dist/chunk-V6WO67RO.js +0 -311
- package/dist/chunk-V6WO67RO.js.map +0 -1
- package/dist/client/styles.css +0 -2
- package/dist/requirement-BEO42QOr.d.cts +0 -387
- package/dist/requirement-BEO42QOr.d.ts +0 -387
package/dist/server/index.d.cts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { A as AuthorizationCode,
|
|
1
|
+
import { A as AuthorizationCode, d as CodeVerifier, H as OAuthSession, I as ClientCredentialsOAuth, f as OAuthAccessToken, g as Offer, P as PaginationParams, h as PaginatedResponse, O as OfferId, i as OfferDetail, j as Participation, k as ParticipationsPaginationParams, l as ParticipationId, m as CreateParticipationParams, n as CreateWalletOwnershipChallengeParams, W as WalletOwnershipChallenge, o as ConnectExternalWalletParams, p as OfferOptionAddress, q as OfferOptionId, r as OfferOptionAddressId, R as Requirement, s as RequirementStatusInfo, t as Pii, D as DocumentType, u as DocumentSubmission, C as CoinListSwapNamespace, K as KycLevelName, v as KycToken, e as Config, J as ClientSecret } from '../requirement-C2w45Q11.cjs';
|
|
2
|
+
import 'viem';
|
|
2
3
|
|
|
3
4
|
interface SessionStore {
|
|
4
5
|
getSession(): Promise<OAuthSession | null>;
|
|
@@ -60,6 +61,21 @@ interface CoinListServer {
|
|
|
60
61
|
* not provide `setSession`.
|
|
61
62
|
*/
|
|
62
63
|
completeOAuth(code: AuthorizationCode, codeVerifier: CodeVerifier): Promise<OAuthSession>;
|
|
64
|
+
/**
|
|
65
|
+
* Obtains an app-level access token via the OAuth 2.0 `client_credentials`
|
|
66
|
+
* grant (RFC 6749 §4.4). No user is involved: the token authenticates the
|
|
67
|
+
* partner application itself and only grants access to app-level resources
|
|
68
|
+
* such as offers and offer requirements.
|
|
69
|
+
*
|
|
70
|
+
* The token is **not** persisted to the {@link SessionStore} and has no
|
|
71
|
+
* refresh token. It expires at `expiresAt`; once expired, call this method
|
|
72
|
+
* again to obtain a fresh token — the SDK does not renew it automatically.
|
|
73
|
+
*
|
|
74
|
+
* Pass the result to {@link fetchOffers}, {@link fetchOffersPage},
|
|
75
|
+
* {@link fetchOfferDetails}, or {@link fetchOfferRequirements} to call them
|
|
76
|
+
* without a user session.
|
|
77
|
+
*/
|
|
78
|
+
clientCredentialsOAuth(): Promise<ClientCredentialsOAuth>;
|
|
63
79
|
/**
|
|
64
80
|
* Returns a valid access token for the current session, refreshing it if
|
|
65
81
|
* it is expired or near expiry.
|
|
@@ -89,21 +105,39 @@ interface CoinListServer {
|
|
|
89
105
|
/**
|
|
90
106
|
* Fetches all offers by iterating through every paginated response.
|
|
91
107
|
*
|
|
92
|
-
*
|
|
108
|
+
* @param clientCreds optional app-level token from
|
|
109
|
+
* {@link clientCredentialsOAuth}. When provided, no user session is
|
|
110
|
+
* required; if a user session exists it takes precedence and `clientCreds`
|
|
111
|
+
* is used as a fallback.
|
|
112
|
+
*
|
|
113
|
+
* Throws {@link NotAuthenticatedError} if there is neither a user session
|
|
114
|
+
* nor `clientCreds`.
|
|
93
115
|
*/
|
|
94
|
-
fetchOffers(): Promise<Offer[]>;
|
|
116
|
+
fetchOffers(clientCreds?: ClientCredentialsOAuth): Promise<Offer[]>;
|
|
95
117
|
/**
|
|
96
118
|
* Fetches a single page of offers.
|
|
97
119
|
*
|
|
98
|
-
*
|
|
120
|
+
* @param clientCreds optional app-level token from
|
|
121
|
+
* {@link clientCredentialsOAuth}. When provided, no user session is
|
|
122
|
+
* required; if a user session exists it takes precedence and `clientCreds`
|
|
123
|
+
* is used as a fallback.
|
|
124
|
+
*
|
|
125
|
+
* Throws {@link NotAuthenticatedError} if there is neither a user session
|
|
126
|
+
* nor `clientCreds`.
|
|
99
127
|
*/
|
|
100
|
-
fetchOffersPage(params: PaginationParams): Promise<PaginatedResponse<Offer>>;
|
|
128
|
+
fetchOffersPage(params: PaginationParams, clientCreds?: ClientCredentialsOAuth): Promise<PaginatedResponse<Offer>>;
|
|
101
129
|
/**
|
|
102
130
|
* Fetches details for a given offer by its id.
|
|
103
131
|
*
|
|
104
|
-
*
|
|
132
|
+
* @param clientCreds optional app-level token from
|
|
133
|
+
* {@link clientCredentialsOAuth}. When provided, no user session is
|
|
134
|
+
* required; if a user session exists it takes precedence and `clientCreds`
|
|
135
|
+
* is used as a fallback.
|
|
136
|
+
*
|
|
137
|
+
* Throws {@link NotAuthenticatedError} if there is neither a user session
|
|
138
|
+
* nor `clientCreds`.
|
|
105
139
|
*/
|
|
106
|
-
fetchOfferDetails(id: OfferId): Promise<OfferDetail>;
|
|
140
|
+
fetchOfferDetails(id: OfferId, clientCreds?: ClientCredentialsOAuth): Promise<OfferDetail>;
|
|
107
141
|
/**
|
|
108
142
|
* Fetches all participations by iterating through every paginated response.
|
|
109
143
|
*
|
|
@@ -129,17 +163,90 @@ interface CoinListServer {
|
|
|
129
163
|
*/
|
|
130
164
|
createParticipation(params: CreateParticipationParams): Promise<Participation>;
|
|
131
165
|
/**
|
|
132
|
-
*
|
|
166
|
+
* Creates a single-use wallet-ownership challenge for the given wallet and
|
|
167
|
+
* chain. The user signs the returned {@link WalletOwnershipChallenge.message}
|
|
168
|
+
* with their wallet, then passes the signature to
|
|
169
|
+
* {@link connectExternalWallet}.
|
|
133
170
|
*
|
|
134
171
|
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
135
172
|
*/
|
|
136
|
-
|
|
173
|
+
createWalletOwnershipChallenge(params: CreateWalletOwnershipChallengeParams): Promise<WalletOwnershipChallenge>;
|
|
174
|
+
/**
|
|
175
|
+
* Connects a proven external wallet to an offer option, using a signature of
|
|
176
|
+
* a challenge from {@link createWalletOwnershipChallenge}.
|
|
177
|
+
*
|
|
178
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
179
|
+
*/
|
|
180
|
+
connectExternalWallet(offerId: OfferId, params: ConnectExternalWalletParams): Promise<OfferOptionAddress>;
|
|
181
|
+
/**
|
|
182
|
+
* Lists the user's proven wallet bindings for a single offer option.
|
|
183
|
+
*
|
|
184
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
185
|
+
*/
|
|
186
|
+
listOptionAddresses(offerId: OfferId, offerOptionId: OfferOptionId): Promise<OfferOptionAddress[]>;
|
|
187
|
+
/**
|
|
188
|
+
* Removes one of the user's wallet bindings and returns the removed binding.
|
|
189
|
+
*
|
|
190
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
191
|
+
*/
|
|
192
|
+
removeOptionAddress(offerId: OfferId, addressId: OfferOptionAddressId): Promise<OfferOptionAddress>;
|
|
193
|
+
/**
|
|
194
|
+
* Fetches the requirements for all options of a given offer, grouped by option ID.
|
|
195
|
+
*
|
|
196
|
+
* @param clientCreds optional app-level token from
|
|
197
|
+
* {@link clientCredentialsOAuth}. When provided, no user session is
|
|
198
|
+
* required; if a user session exists it takes precedence and `clientCreds`
|
|
199
|
+
* is used as a fallback.
|
|
200
|
+
*
|
|
201
|
+
* Throws {@link NotAuthenticatedError} if there is neither a user session
|
|
202
|
+
* nor `clientCreds`.
|
|
203
|
+
*/
|
|
204
|
+
fetchOfferRequirements(offerId: OfferId, clientCreds?: ClientCredentialsOAuth): Promise<Record<OfferOptionId, Requirement[]>>;
|
|
137
205
|
/**
|
|
138
206
|
* Fetches the user's requirement statuses for a given offer.
|
|
139
207
|
*
|
|
140
208
|
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
141
209
|
*/
|
|
142
210
|
fetchRequirementStatuses(offerId: OfferId): Promise<RequirementStatusInfo[]>;
|
|
211
|
+
/**
|
|
212
|
+
* Fetches the user's PII (tax form pre-fill data) — full legal name, date
|
|
213
|
+
* of birth, jurisdiction, tax ID, and permanent address for an individual;
|
|
214
|
+
* or the equivalent entity fields for a company/trust, used to pre-fill a
|
|
215
|
+
* W-8BEN. Fields the entity hasn't provided are `null`.
|
|
216
|
+
*
|
|
217
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
218
|
+
*/
|
|
219
|
+
fetchPii(): Promise<Pii>;
|
|
220
|
+
/**
|
|
221
|
+
* Starts (or resumes) a document signing submission for the given type
|
|
222
|
+
* (currently only `tax_certification`, e.g. W-8BEN/W-8BEN-E). `fields` are
|
|
223
|
+
* signing-form values keyed by the document's DocuSeal field names,
|
|
224
|
+
* forwarded verbatim to Passport to pre-fill the document.
|
|
225
|
+
*
|
|
226
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
227
|
+
*/
|
|
228
|
+
submitDocument(documentType: DocumentType, fields: Record<string, string>): Promise<DocumentSubmission>;
|
|
229
|
+
/**
|
|
230
|
+
* On-chain swap operations: quoting a swap, reading swap-contract state and
|
|
231
|
+
* token allowances, and proving/allow-listing wallet ownership — e.g.
|
|
232
|
+
* `coinlist.swap.getOutputToken({ contractAddress, chain })`.
|
|
233
|
+
*
|
|
234
|
+
* These methods require a user session and throw
|
|
235
|
+
* {@link NotAuthenticatedError} if the user is not authenticated.
|
|
236
|
+
*/
|
|
237
|
+
readonly swap: CoinListSwapNamespace;
|
|
238
|
+
/**
|
|
239
|
+
* Creates a short-lived Sumsub WebSDK access token for the current user so
|
|
240
|
+
* an identity verification (KYC) flow can be started, e.g. to seed the
|
|
241
|
+
* client-side `IdentityVerification` component when server-rendering.
|
|
242
|
+
* `levelName` selects the Sumsub verification level; defaults to the
|
|
243
|
+
* backend's standard level. `reset` resets the Sumsub applicant first, so
|
|
244
|
+
* an already-approved level can be executed again (e.g. to update stale
|
|
245
|
+
* PII).
|
|
246
|
+
*
|
|
247
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
248
|
+
*/
|
|
249
|
+
createKycToken(levelName?: KycLevelName, reset?: boolean): Promise<KycToken>;
|
|
143
250
|
}
|
|
144
251
|
declare function createCoinListServer(config: ServerConfig): CoinListServer;
|
|
145
252
|
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { A as AuthorizationCode,
|
|
1
|
+
import { A as AuthorizationCode, d as CodeVerifier, H as OAuthSession, I as ClientCredentialsOAuth, f as OAuthAccessToken, g as Offer, P as PaginationParams, h as PaginatedResponse, O as OfferId, i as OfferDetail, j as Participation, k as ParticipationsPaginationParams, l as ParticipationId, m as CreateParticipationParams, n as CreateWalletOwnershipChallengeParams, W as WalletOwnershipChallenge, o as ConnectExternalWalletParams, p as OfferOptionAddress, q as OfferOptionId, r as OfferOptionAddressId, R as Requirement, s as RequirementStatusInfo, t as Pii, D as DocumentType, u as DocumentSubmission, C as CoinListSwapNamespace, K as KycLevelName, v as KycToken, e as Config, J as ClientSecret } from '../requirement-C2w45Q11.js';
|
|
2
|
+
import 'viem';
|
|
2
3
|
|
|
3
4
|
interface SessionStore {
|
|
4
5
|
getSession(): Promise<OAuthSession | null>;
|
|
@@ -60,6 +61,21 @@ interface CoinListServer {
|
|
|
60
61
|
* not provide `setSession`.
|
|
61
62
|
*/
|
|
62
63
|
completeOAuth(code: AuthorizationCode, codeVerifier: CodeVerifier): Promise<OAuthSession>;
|
|
64
|
+
/**
|
|
65
|
+
* Obtains an app-level access token via the OAuth 2.0 `client_credentials`
|
|
66
|
+
* grant (RFC 6749 §4.4). No user is involved: the token authenticates the
|
|
67
|
+
* partner application itself and only grants access to app-level resources
|
|
68
|
+
* such as offers and offer requirements.
|
|
69
|
+
*
|
|
70
|
+
* The token is **not** persisted to the {@link SessionStore} and has no
|
|
71
|
+
* refresh token. It expires at `expiresAt`; once expired, call this method
|
|
72
|
+
* again to obtain a fresh token — the SDK does not renew it automatically.
|
|
73
|
+
*
|
|
74
|
+
* Pass the result to {@link fetchOffers}, {@link fetchOffersPage},
|
|
75
|
+
* {@link fetchOfferDetails}, or {@link fetchOfferRequirements} to call them
|
|
76
|
+
* without a user session.
|
|
77
|
+
*/
|
|
78
|
+
clientCredentialsOAuth(): Promise<ClientCredentialsOAuth>;
|
|
63
79
|
/**
|
|
64
80
|
* Returns a valid access token for the current session, refreshing it if
|
|
65
81
|
* it is expired or near expiry.
|
|
@@ -89,21 +105,39 @@ interface CoinListServer {
|
|
|
89
105
|
/**
|
|
90
106
|
* Fetches all offers by iterating through every paginated response.
|
|
91
107
|
*
|
|
92
|
-
*
|
|
108
|
+
* @param clientCreds optional app-level token from
|
|
109
|
+
* {@link clientCredentialsOAuth}. When provided, no user session is
|
|
110
|
+
* required; if a user session exists it takes precedence and `clientCreds`
|
|
111
|
+
* is used as a fallback.
|
|
112
|
+
*
|
|
113
|
+
* Throws {@link NotAuthenticatedError} if there is neither a user session
|
|
114
|
+
* nor `clientCreds`.
|
|
93
115
|
*/
|
|
94
|
-
fetchOffers(): Promise<Offer[]>;
|
|
116
|
+
fetchOffers(clientCreds?: ClientCredentialsOAuth): Promise<Offer[]>;
|
|
95
117
|
/**
|
|
96
118
|
* Fetches a single page of offers.
|
|
97
119
|
*
|
|
98
|
-
*
|
|
120
|
+
* @param clientCreds optional app-level token from
|
|
121
|
+
* {@link clientCredentialsOAuth}. When provided, no user session is
|
|
122
|
+
* required; if a user session exists it takes precedence and `clientCreds`
|
|
123
|
+
* is used as a fallback.
|
|
124
|
+
*
|
|
125
|
+
* Throws {@link NotAuthenticatedError} if there is neither a user session
|
|
126
|
+
* nor `clientCreds`.
|
|
99
127
|
*/
|
|
100
|
-
fetchOffersPage(params: PaginationParams): Promise<PaginatedResponse<Offer>>;
|
|
128
|
+
fetchOffersPage(params: PaginationParams, clientCreds?: ClientCredentialsOAuth): Promise<PaginatedResponse<Offer>>;
|
|
101
129
|
/**
|
|
102
130
|
* Fetches details for a given offer by its id.
|
|
103
131
|
*
|
|
104
|
-
*
|
|
132
|
+
* @param clientCreds optional app-level token from
|
|
133
|
+
* {@link clientCredentialsOAuth}. When provided, no user session is
|
|
134
|
+
* required; if a user session exists it takes precedence and `clientCreds`
|
|
135
|
+
* is used as a fallback.
|
|
136
|
+
*
|
|
137
|
+
* Throws {@link NotAuthenticatedError} if there is neither a user session
|
|
138
|
+
* nor `clientCreds`.
|
|
105
139
|
*/
|
|
106
|
-
fetchOfferDetails(id: OfferId): Promise<OfferDetail>;
|
|
140
|
+
fetchOfferDetails(id: OfferId, clientCreds?: ClientCredentialsOAuth): Promise<OfferDetail>;
|
|
107
141
|
/**
|
|
108
142
|
* Fetches all participations by iterating through every paginated response.
|
|
109
143
|
*
|
|
@@ -129,17 +163,90 @@ interface CoinListServer {
|
|
|
129
163
|
*/
|
|
130
164
|
createParticipation(params: CreateParticipationParams): Promise<Participation>;
|
|
131
165
|
/**
|
|
132
|
-
*
|
|
166
|
+
* Creates a single-use wallet-ownership challenge for the given wallet and
|
|
167
|
+
* chain. The user signs the returned {@link WalletOwnershipChallenge.message}
|
|
168
|
+
* with their wallet, then passes the signature to
|
|
169
|
+
* {@link connectExternalWallet}.
|
|
133
170
|
*
|
|
134
171
|
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
135
172
|
*/
|
|
136
|
-
|
|
173
|
+
createWalletOwnershipChallenge(params: CreateWalletOwnershipChallengeParams): Promise<WalletOwnershipChallenge>;
|
|
174
|
+
/**
|
|
175
|
+
* Connects a proven external wallet to an offer option, using a signature of
|
|
176
|
+
* a challenge from {@link createWalletOwnershipChallenge}.
|
|
177
|
+
*
|
|
178
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
179
|
+
*/
|
|
180
|
+
connectExternalWallet(offerId: OfferId, params: ConnectExternalWalletParams): Promise<OfferOptionAddress>;
|
|
181
|
+
/**
|
|
182
|
+
* Lists the user's proven wallet bindings for a single offer option.
|
|
183
|
+
*
|
|
184
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
185
|
+
*/
|
|
186
|
+
listOptionAddresses(offerId: OfferId, offerOptionId: OfferOptionId): Promise<OfferOptionAddress[]>;
|
|
187
|
+
/**
|
|
188
|
+
* Removes one of the user's wallet bindings and returns the removed binding.
|
|
189
|
+
*
|
|
190
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
191
|
+
*/
|
|
192
|
+
removeOptionAddress(offerId: OfferId, addressId: OfferOptionAddressId): Promise<OfferOptionAddress>;
|
|
193
|
+
/**
|
|
194
|
+
* Fetches the requirements for all options of a given offer, grouped by option ID.
|
|
195
|
+
*
|
|
196
|
+
* @param clientCreds optional app-level token from
|
|
197
|
+
* {@link clientCredentialsOAuth}. When provided, no user session is
|
|
198
|
+
* required; if a user session exists it takes precedence and `clientCreds`
|
|
199
|
+
* is used as a fallback.
|
|
200
|
+
*
|
|
201
|
+
* Throws {@link NotAuthenticatedError} if there is neither a user session
|
|
202
|
+
* nor `clientCreds`.
|
|
203
|
+
*/
|
|
204
|
+
fetchOfferRequirements(offerId: OfferId, clientCreds?: ClientCredentialsOAuth): Promise<Record<OfferOptionId, Requirement[]>>;
|
|
137
205
|
/**
|
|
138
206
|
* Fetches the user's requirement statuses for a given offer.
|
|
139
207
|
*
|
|
140
208
|
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
141
209
|
*/
|
|
142
210
|
fetchRequirementStatuses(offerId: OfferId): Promise<RequirementStatusInfo[]>;
|
|
211
|
+
/**
|
|
212
|
+
* Fetches the user's PII (tax form pre-fill data) — full legal name, date
|
|
213
|
+
* of birth, jurisdiction, tax ID, and permanent address for an individual;
|
|
214
|
+
* or the equivalent entity fields for a company/trust, used to pre-fill a
|
|
215
|
+
* W-8BEN. Fields the entity hasn't provided are `null`.
|
|
216
|
+
*
|
|
217
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
218
|
+
*/
|
|
219
|
+
fetchPii(): Promise<Pii>;
|
|
220
|
+
/**
|
|
221
|
+
* Starts (or resumes) a document signing submission for the given type
|
|
222
|
+
* (currently only `tax_certification`, e.g. W-8BEN/W-8BEN-E). `fields` are
|
|
223
|
+
* signing-form values keyed by the document's DocuSeal field names,
|
|
224
|
+
* forwarded verbatim to Passport to pre-fill the document.
|
|
225
|
+
*
|
|
226
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
227
|
+
*/
|
|
228
|
+
submitDocument(documentType: DocumentType, fields: Record<string, string>): Promise<DocumentSubmission>;
|
|
229
|
+
/**
|
|
230
|
+
* On-chain swap operations: quoting a swap, reading swap-contract state and
|
|
231
|
+
* token allowances, and proving/allow-listing wallet ownership — e.g.
|
|
232
|
+
* `coinlist.swap.getOutputToken({ contractAddress, chain })`.
|
|
233
|
+
*
|
|
234
|
+
* These methods require a user session and throw
|
|
235
|
+
* {@link NotAuthenticatedError} if the user is not authenticated.
|
|
236
|
+
*/
|
|
237
|
+
readonly swap: CoinListSwapNamespace;
|
|
238
|
+
/**
|
|
239
|
+
* Creates a short-lived Sumsub WebSDK access token for the current user so
|
|
240
|
+
* an identity verification (KYC) flow can be started, e.g. to seed the
|
|
241
|
+
* client-side `IdentityVerification` component when server-rendering.
|
|
242
|
+
* `levelName` selects the Sumsub verification level; defaults to the
|
|
243
|
+
* backend's standard level. `reset` resets the Sumsub applicant first, so
|
|
244
|
+
* an already-approved level can be executed again (e.g. to update stale
|
|
245
|
+
* PII).
|
|
246
|
+
*
|
|
247
|
+
* Throws {@link NotAuthenticatedError} if the user is not authenticated.
|
|
248
|
+
*/
|
|
249
|
+
createKycToken(levelName?: KycLevelName, reset?: boolean): Promise<KycToken>;
|
|
143
250
|
}
|
|
144
251
|
declare function createCoinListServer(config: ServerConfig): CoinListServer;
|
|
145
252
|
|
package/dist/server/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
AuthenticatedApiClient,
|
|
4
4
|
HttpError,
|
|
5
5
|
PUBLIC_API_BASE_URL,
|
|
6
|
+
createKycToken,
|
|
6
7
|
createParticipation,
|
|
7
8
|
fetchOfferDetails,
|
|
8
9
|
fetchOfferRequirements,
|
|
@@ -11,14 +12,22 @@ import {
|
|
|
11
12
|
fetchParticipation,
|
|
12
13
|
fetchParticipations,
|
|
13
14
|
fetchParticipationsPage,
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
fetchPii,
|
|
16
|
+
fetchRequirementStatuses,
|
|
17
|
+
submitDocument
|
|
18
|
+
} from "../chunk-MKCOK3DF.js";
|
|
16
19
|
import {
|
|
20
|
+
ClientCredentialsOAuth,
|
|
17
21
|
OAuthSession
|
|
18
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-AAER5LOL.js";
|
|
19
23
|
import {
|
|
20
|
-
NotAuthenticatedError
|
|
21
|
-
|
|
24
|
+
NotAuthenticatedError,
|
|
25
|
+
SwapNamespaceImpl,
|
|
26
|
+
connectExternalWallet,
|
|
27
|
+
createWalletOwnershipChallenge,
|
|
28
|
+
listOptionAddresses,
|
|
29
|
+
removeOptionAddress
|
|
30
|
+
} from "../chunk-Z2HAA2TI.js";
|
|
22
31
|
|
|
23
32
|
// src/server/api/api.server.ts
|
|
24
33
|
var Api = class {
|
|
@@ -57,6 +66,10 @@ var CoinListServerImpl = class {
|
|
|
57
66
|
// than re-sending with the same expired token and wasting a round-trip.
|
|
58
67
|
(refresh) => refresh && !this._config.sessionStore.setSession ? Promise.resolve(null) : this.accessToken()
|
|
59
68
|
);
|
|
69
|
+
this.swap = new SwapNamespaceImpl({
|
|
70
|
+
api: this.api,
|
|
71
|
+
ensureUserAuthenticated: () => this.ensureUserAuthenticated()
|
|
72
|
+
});
|
|
60
73
|
}
|
|
61
74
|
async completeOAuth(code, codeVerifier) {
|
|
62
75
|
const sessionStore = this._config.sessionStore;
|
|
@@ -80,6 +93,19 @@ var CoinListServerImpl = class {
|
|
|
80
93
|
await setSession(session);
|
|
81
94
|
return session;
|
|
82
95
|
}
|
|
96
|
+
async clientCredentialsOAuth() {
|
|
97
|
+
const sessionDto = await this.api.send({
|
|
98
|
+
method: "POST",
|
|
99
|
+
url: `/oauth/token`,
|
|
100
|
+
body: {
|
|
101
|
+
grant_type: "client_credentials",
|
|
102
|
+
client_id: this._config.clientId,
|
|
103
|
+
client_secret: this._config.clientSecret
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
const session = OAuthSession.fromDto(sessionDto);
|
|
107
|
+
return ClientCredentialsOAuth(session.accessToken);
|
|
108
|
+
}
|
|
83
109
|
async accessToken() {
|
|
84
110
|
const sessionStore = this._config.sessionStore;
|
|
85
111
|
const session = await sessionStore.getSession();
|
|
@@ -152,48 +178,89 @@ var CoinListServerImpl = class {
|
|
|
152
178
|
await setSession(null);
|
|
153
179
|
}
|
|
154
180
|
}
|
|
155
|
-
async
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
throw new NotAuthenticatedError();
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
async fetchOffers() {
|
|
162
|
-
await this.ensureAuthenticated();
|
|
163
|
-
return fetchOffers(this.api);
|
|
181
|
+
async fetchOffers(clientCreds) {
|
|
182
|
+
await this.ensureAuthenticated(clientCreds);
|
|
183
|
+
return fetchOffers(this.api, clientCreds);
|
|
164
184
|
}
|
|
165
|
-
async fetchOffersPage(params) {
|
|
166
|
-
await this.ensureAuthenticated();
|
|
167
|
-
return fetchOffersPage(this.api, params);
|
|
185
|
+
async fetchOffersPage(params, clientCreds) {
|
|
186
|
+
await this.ensureAuthenticated(clientCreds);
|
|
187
|
+
return fetchOffersPage(this.api, params, clientCreds);
|
|
168
188
|
}
|
|
169
|
-
async fetchOfferDetails(id) {
|
|
170
|
-
await this.ensureAuthenticated();
|
|
171
|
-
return fetchOfferDetails(this.api, id);
|
|
189
|
+
async fetchOfferDetails(id, clientCreds) {
|
|
190
|
+
await this.ensureAuthenticated(clientCreds);
|
|
191
|
+
return fetchOfferDetails(this.api, id, clientCreds);
|
|
172
192
|
}
|
|
173
193
|
async fetchParticipations(offerId) {
|
|
174
|
-
await this.
|
|
194
|
+
await this.ensureUserAuthenticated();
|
|
175
195
|
return fetchParticipations(this.api, offerId);
|
|
176
196
|
}
|
|
177
197
|
async fetchParticipationsPage(params) {
|
|
178
|
-
await this.
|
|
198
|
+
await this.ensureUserAuthenticated();
|
|
179
199
|
return fetchParticipationsPage(this.api, params);
|
|
180
200
|
}
|
|
181
201
|
async fetchParticipation(id) {
|
|
182
|
-
await this.
|
|
202
|
+
await this.ensureUserAuthenticated();
|
|
183
203
|
return fetchParticipation(this.api, id);
|
|
184
204
|
}
|
|
185
205
|
async createParticipation(params) {
|
|
186
|
-
await this.
|
|
206
|
+
await this.ensureUserAuthenticated();
|
|
187
207
|
return createParticipation(this.api, params);
|
|
188
208
|
}
|
|
189
|
-
async
|
|
190
|
-
await this.
|
|
191
|
-
return
|
|
209
|
+
async createWalletOwnershipChallenge(params) {
|
|
210
|
+
await this.ensureUserAuthenticated();
|
|
211
|
+
return createWalletOwnershipChallenge(this.api, params);
|
|
212
|
+
}
|
|
213
|
+
async connectExternalWallet(offerId, params) {
|
|
214
|
+
await this.ensureUserAuthenticated();
|
|
215
|
+
return connectExternalWallet(this.api, offerId, params);
|
|
216
|
+
}
|
|
217
|
+
async listOptionAddresses(offerId, offerOptionId) {
|
|
218
|
+
await this.ensureUserAuthenticated();
|
|
219
|
+
return listOptionAddresses(
|
|
220
|
+
this.api,
|
|
221
|
+
offerId,
|
|
222
|
+
offerOptionId
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
async removeOptionAddress(offerId, addressId) {
|
|
226
|
+
await this.ensureUserAuthenticated();
|
|
227
|
+
return removeOptionAddress(this.api, offerId, addressId);
|
|
228
|
+
}
|
|
229
|
+
async fetchOfferRequirements(offerId, clientCreds) {
|
|
230
|
+
await this.ensureAuthenticated(clientCreds);
|
|
231
|
+
return fetchOfferRequirements(
|
|
232
|
+
this.api,
|
|
233
|
+
offerId,
|
|
234
|
+
clientCreds
|
|
235
|
+
);
|
|
192
236
|
}
|
|
193
237
|
async fetchRequirementStatuses(offerId) {
|
|
194
|
-
await this.
|
|
238
|
+
await this.ensureUserAuthenticated();
|
|
195
239
|
return fetchRequirementStatuses(this.api, offerId);
|
|
196
240
|
}
|
|
241
|
+
async ensureAuthenticated(clientCreds) {
|
|
242
|
+
if (!clientCreds) {
|
|
243
|
+
await this.ensureUserAuthenticated();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
async ensureUserAuthenticated() {
|
|
247
|
+
const token = await this.accessToken();
|
|
248
|
+
if (token === null) {
|
|
249
|
+
throw new NotAuthenticatedError();
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
async fetchPii() {
|
|
253
|
+
await this.ensureUserAuthenticated();
|
|
254
|
+
return fetchPii(this.api);
|
|
255
|
+
}
|
|
256
|
+
async submitDocument(documentType, fields) {
|
|
257
|
+
await this.ensureUserAuthenticated();
|
|
258
|
+
return submitDocument(this.api, documentType, fields);
|
|
259
|
+
}
|
|
260
|
+
async createKycToken(levelName, reset) {
|
|
261
|
+
await this.ensureUserAuthenticated();
|
|
262
|
+
return createKycToken(this.api, levelName, reset);
|
|
263
|
+
}
|
|
197
264
|
};
|
|
198
265
|
function createCoinListServer(config) {
|
|
199
266
|
return new CoinListServerImpl(config);
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/server/api/api.server.ts","../../src/server/errors.ts","../../src/server/coinlist.server.ts"],"sourcesContent":["import { AuthenticatedApiClient } from '@/shared/api/authenticated-api-client';\nimport type { HttpClientConfig, HttpRequest } from '@/shared/api/http';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\n\nexport class Api {\n private readonly client: AuthenticatedApiClient;\n\n constructor(\n config: HttpClientConfig,\n fetchAccessToken: (refresh: boolean) => Promise<OAuthAccessToken | null>\n ) {\n this.client = new AuthenticatedApiClient(config, fetchAccessToken);\n }\n\n async send<TResponse>(request: HttpRequest): Promise<TResponse> {\n return this.client.send<TResponse>(request);\n }\n}\n","export class WritableSessionStoreRequiredError extends Error {\n constructor(\n message = 'This operation requires a writable SessionStore. Provide a `setSession` implementation in your SessionStore to persist or clear OAuth sessions.'\n ) {\n super(message);\n this.name = 'WritableSessionStoreRequiredError';\n }\n}\n","import { Api } from '@/server/api/api.server';\nimport { WritableSessionStoreRequiredError } from '@/server/errors';\nimport {\n API_VERSION,\n PUBLIC_API_BASE_URL,\n} from '@/shared/api/frontline/config';\nimport * as offersApi from '@/shared/api/frontline/offers';\nimport * as participationsApi from '@/shared/api/frontline/participations';\nimport * as requirementsApi from '@/shared/api/frontline/requirements';\nimport { HttpError } from '@/shared/api/http';\nimport type {\n PaginatedResponse,\n PaginationParams,\n} from '@/shared/api/pagination';\nimport type { Config } from '@/shared/types/config';\nimport type { OAuthSessionDto } from '@/shared/types/dto/oauth-session';\nimport { NotAuthenticatedError } from '@/shared/types/errors';\nimport type {\n AuthorizationCode,\n ClientSecret,\n CodeVerifier,\n} from '@/shared/types/oauth';\nimport {\n type OAuthAccessToken,\n type OAuthRefreshToken,\n OAuthSession,\n} from '@/shared/types/oauth-session';\nimport type { Offer, OfferId } from '@/shared/types/offer';\nimport type { OfferDetail, OfferOptionId } from '@/shared/types/offer-detail';\nimport type {\n CreateParticipationParams,\n Participation,\n ParticipationId,\n ParticipationsPaginationParams,\n} from '@/shared/types/participation';\nimport type {\n Requirement,\n RequirementStatusInfo,\n} from '@/shared/types/requirement';\n\n/** Buffer in seconds before expiry to consider token expired for refresh. */\nconst ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS = 60;\n\nexport interface SessionStore {\n getSession(): Promise<OAuthSession | null>;\n /**\n * Persists or clears the OAuth session.\n *\n * **Omit this method to create a read-only store.** When absent, the SDK\n * skips token refresh entirely — no network call is made and no refresh\n * token is consumed. This is the correct approach for contexts that can read\n * the session but cannot write it back, such as Next.js Server Components.\n *\n * ⚠️ Do **not** implement this as a no-op (`async () => {}`). If the method\n * is present, the SDK assumes writes succeed: it will fire a token refresh\n * network call, consume the refresh token, then invoke `setSession` — which\n * would silently discard the new session and leave the browser holding an\n * invalidated refresh token. Simply **omit** `setSession` to prevent any\n * refresh from being attempted.\n *\n * {@link CoinListServer.completeOAuth} and {@link CoinListServer.logout}\n * always require a writable store and throw\n * {@link WritableSessionStoreRequiredError} if `setSession` is absent.\n */\n setSession?(session: OAuthSession | null): Promise<void>;\n}\n\nexport interface ServerConfig extends Config {\n readonly clientSecret: ClientSecret;\n readonly sessionStore: SessionStore;\n /** Buffer in seconds before expiry to consider token expired for refresh. */\n readonly accessTokenExpiryBufferSeconds?: number;\n /**\n * Whether SDK will throw an exception in cases it can be silent.\n * For example, if token revokation on logout fails.\n */\n readonly strict?: boolean;\n}\n\n/**\n * Server-side CoinList SDK client.\n *\n * Operates in one of two modes depending on whether {@link SessionStore}\n * includes a `setSession` implementation:\n *\n * - **Writable store** (`setSession` provided) — full functionality: token\n * refresh, {@link completeOAuth}, and {@link logout} all work normally.\n *\n * - **Read-only store** (no `setSession`) — token refresh is skipped entirely,\n * meaning no network call is made and no refresh token is consumed.\n * {@link completeOAuth} and {@link logout} throw\n * {@link WritableSessionStoreRequiredError}. {@link accessToken} may return\n * an expired token (see its docs). Use this mode in execution contexts that\n * can read the session but cannot write it back, such as Next.js Server\n * Components.\n */\nexport interface CoinListServer {\n /**\n * Exchanges an authorization code for an OAuth session and persists it via\n * {@link SessionStore.setSession}.\n *\n * Throws {@link WritableSessionStoreRequiredError} if the session store does\n * not provide `setSession`.\n */\n completeOAuth(\n code: AuthorizationCode,\n codeVerifier: CodeVerifier\n ): Promise<OAuthSession>;\n\n /**\n * Returns a valid access token for the current session, refreshing it if\n * it is expired or near expiry.\n *\n * **Writable store**: if the token is expired, the SDK exchanges the refresh\n * token for a new session, persists it, and returns the fresh access token.\n * Returns `null` if there is no session or the refresh fails.\n *\n * **Read-only store** (no `setSession`): refresh is skipped entirely. The\n * stored token is returned as-is, even if it is expired — a non-null return\n * value does **not** guarantee the token is accepted by the API. Before\n * making API calls, check `token.expiresAt > new Date()`. Use a writable\n * store (e.g. in a Route Handler) when you need the SDK to renew the session\n * automatically.\n *\n * @returns the access token, or `null` if there is no session or the session\n * could not be refreshed.\n */\n accessToken(): Promise<OAuthAccessToken | null>;\n\n /**\n * Revokes the current token via POST /oauth/revoke and clears the session.\n *\n * Throws {@link WritableSessionStoreRequiredError} if the session store does\n * not provide `setSession`.\n */\n logout(): Promise<void>;\n\n /**\n * Fetches all offers by iterating through every paginated response.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchOffers(): Promise<Offer[]>;\n\n /**\n * Fetches a single page of offers.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchOffersPage(params: PaginationParams): Promise<PaginatedResponse<Offer>>;\n\n /**\n * Fetches details for a given offer by its id.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchOfferDetails(id: OfferId): Promise<OfferDetail>;\n\n /**\n * Fetches all participations by iterating through every paginated response.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchParticipations(offerId?: OfferId): Promise<Participation[]>;\n\n /**\n * Fetches a single page of participations, optionally filtered by offer.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchParticipationsPage(\n params: ParticipationsPaginationParams\n ): Promise<PaginatedResponse<Participation>>;\n\n /**\n * Fetches a participation by id.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchParticipation(id: ParticipationId): Promise<Participation>;\n\n /**\n * Creates a participation.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n createParticipation(\n params: CreateParticipationParams\n ): Promise<Participation>;\n\n /**\n * Fetches the requirements for all options of a given offer, grouped by option ID.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchOfferRequirements(\n offerId: OfferId\n ): Promise<Record<OfferOptionId, Requirement[]>>;\n\n /**\n * Fetches the user's requirement statuses for a given offer.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchRequirementStatuses(offerId: OfferId): Promise<RequirementStatusInfo[]>;\n}\n\nclass CoinListServerImpl implements CoinListServer {\n private readonly api: Api;\n private readonly baseUrl: string;\n\n private readonly accessTokenExpiryBufferSeconds: number;\n private readonly strict: boolean;\n\n constructor(private readonly _config: ServerConfig) {\n this.baseUrl = _config.baseUrl ?? PUBLIC_API_BASE_URL;\n this.accessTokenExpiryBufferSeconds =\n _config.accessTokenExpiryBufferSeconds ??\n ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS;\n this.strict = _config.strict ?? false;\n this.api = new Api(\n {\n baseUrl: this.baseUrl,\n xApiVersion: API_VERSION,\n },\n // When refresh=true the renewal middleware has received a 401 and wants a\n // fresh token. A read-only store cannot persist a new session, so return\n // null immediately — this tells the middleware to skip the retry rather\n // than re-sending with the same expired token and wasting a round-trip.\n (refresh) =>\n refresh && !this._config.sessionStore.setSession\n ? Promise.resolve(null)\n : this.accessToken()\n );\n }\n\n async completeOAuth(\n code: AuthorizationCode,\n codeVerifier: CodeVerifier\n ): Promise<OAuthSession> {\n const sessionStore = this._config.sessionStore;\n const setSession = sessionStore.setSession?.bind(sessionStore);\n if (!setSession) {\n throw new WritableSessionStoreRequiredError();\n }\n const sessionDto = await this.api.send<OAuthSessionDto>({\n method: 'POST',\n url: `/oauth/token`,\n body: {\n grant_type: 'authorization_code',\n code,\n redirect_uri: this._config.redirectUri,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n code_verifier: codeVerifier,\n },\n });\n const session = OAuthSession.fromDto(sessionDto);\n await setSession(session);\n return session;\n }\n\n async accessToken(): Promise<OAuthAccessToken | null> {\n const sessionStore = this._config.sessionStore;\n const session = await sessionStore.getSession();\n if (session == null) return null;\n\n const now = Date.now();\n const expiresAt = session.accessToken.expiresAt.getTime();\n const bufferMs = this.accessTokenExpiryBufferSeconds * 1000;\n if (expiresAt > now + bufferMs) {\n // Valid access token, return it regardless\n return session.accessToken;\n }\n\n const setSession = sessionStore.setSession?.bind(sessionStore);\n if (!setSession) {\n // No write session capabilities => can't refresh!\n // Return the access token as-is\n return session.accessToken;\n } else {\n return this.refreshSession(session.refreshToken, setSession);\n }\n }\n\n private async refreshSession(\n refreshToken: OAuthRefreshToken | undefined,\n setSession: (session: OAuthSession | null) => Promise<void>\n ): Promise<OAuthAccessToken | null> {\n if (!refreshToken) {\n await setSession(null);\n return null;\n }\n\n try {\n const sessionDto = await this.api.send<OAuthSessionDto>({\n method: 'POST',\n url: `/oauth/token`,\n body: {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n },\n });\n const newSession = OAuthSession.fromDto(sessionDto);\n await setSession(newSession);\n return newSession.accessToken;\n } catch {\n await setSession(null);\n return null;\n }\n }\n\n async logout(): Promise<void> {\n const sessionStore = this._config.sessionStore;\n const setSession = sessionStore.setSession?.bind(sessionStore);\n if (!setSession) {\n throw new WritableSessionStoreRequiredError();\n }\n const session = await sessionStore.getSession();\n if (session != null) {\n const tokenToRevoke = session.accessToken.value;\n try {\n await this.api.send({\n method: 'POST',\n url: `/oauth/revoke`,\n body: {\n token: tokenToRevoke,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n },\n });\n } catch (err) {\n if (err instanceof HttpError) {\n if (this.strict) {\n throw err;\n }\n } else {\n throw err;\n }\n }\n // invalidate the session\n await setSession(null);\n }\n }\n\n private async ensureAuthenticated(): Promise<void> {\n const token = await this.accessToken();\n if (token === null) {\n throw new NotAuthenticatedError();\n }\n }\n\n async fetchOffers(): Promise<Offer[]> {\n await this.ensureAuthenticated();\n return offersApi.fetchOffers(this.api);\n }\n\n async fetchOffersPage(\n params: PaginationParams\n ): Promise<PaginatedResponse<Offer>> {\n await this.ensureAuthenticated();\n return offersApi.fetchOffersPage(this.api, params);\n }\n\n async fetchOfferDetails(id: OfferId): Promise<OfferDetail> {\n await this.ensureAuthenticated();\n return offersApi.fetchOfferDetails(this.api, id);\n }\n\n async fetchParticipations(offerId?: OfferId): Promise<Participation[]> {\n await this.ensureAuthenticated();\n return participationsApi.fetchParticipations(this.api, offerId);\n }\n\n async fetchParticipationsPage(\n params: ParticipationsPaginationParams\n ): Promise<PaginatedResponse<Participation>> {\n await this.ensureAuthenticated();\n return participationsApi.fetchParticipationsPage(this.api, params);\n }\n\n async fetchParticipation(id: ParticipationId): Promise<Participation> {\n await this.ensureAuthenticated();\n return participationsApi.fetchParticipation(this.api, id);\n }\n\n async createParticipation(\n params: CreateParticipationParams\n ): Promise<Participation> {\n await this.ensureAuthenticated();\n return participationsApi.createParticipation(this.api, params);\n }\n\n async fetchOfferRequirements(\n offerId: OfferId\n ): Promise<Record<OfferOptionId, Requirement[]>> {\n await this.ensureAuthenticated();\n return requirementsApi.fetchOfferRequirements(this.api, offerId);\n }\n\n async fetchRequirementStatuses(\n offerId: OfferId\n ): Promise<RequirementStatusInfo[]> {\n await this.ensureAuthenticated();\n return requirementsApi.fetchRequirementStatuses(this.api, offerId);\n }\n}\n\nexport function createCoinListServer(config: ServerConfig): CoinListServer {\n return new CoinListServerImpl(config);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/server/api/api.server.ts","../../src/server/errors.ts","../../src/server/coinlist.server.ts"],"sourcesContent":["import { AuthenticatedApiClient } from '@/shared/api/authenticated-api-client';\nimport type { HttpClientConfig, HttpRequest } from '@/shared/api/http';\nimport type { OAuthAccessToken } from '@/shared/types/oauth-session';\n\nexport class Api {\n private readonly client: AuthenticatedApiClient;\n\n constructor(\n config: HttpClientConfig,\n fetchAccessToken: (refresh: boolean) => Promise<OAuthAccessToken | null>\n ) {\n this.client = new AuthenticatedApiClient(config, fetchAccessToken);\n }\n\n async send<TResponse>(request: HttpRequest): Promise<TResponse> {\n return this.client.send<TResponse>(request);\n }\n}\n","export class WritableSessionStoreRequiredError extends Error {\n constructor(\n message = 'This operation requires a writable SessionStore. Provide a `setSession` implementation in your SessionStore to persist or clear OAuth sessions.'\n ) {\n super(message);\n this.name = 'WritableSessionStoreRequiredError';\n }\n}\n","import { Api } from '@/server/api/api.server';\nimport { WritableSessionStoreRequiredError } from '@/server/errors';\nimport {\n API_VERSION,\n PUBLIC_API_BASE_URL,\n} from '@/shared/api/frontline/config';\nimport * as documentsApi from '@/shared/api/frontline/documents';\nimport * as kycApi from '@/shared/api/frontline/kyc';\nimport * as offersApi from '@/shared/api/frontline/offers';\nimport * as participationsApi from '@/shared/api/frontline/participations';\nimport * as piiApi from '@/shared/api/frontline/pii';\nimport * as requirementsApi from '@/shared/api/frontline/requirements';\nimport * as walletConnectApi from '@/shared/api/frontline/wallet-connect';\nimport { HttpError } from '@/shared/api/http';\nimport type {\n PaginatedResponse,\n PaginationParams,\n} from '@/shared/api/pagination';\nimport {\n type CoinListSwapNamespace,\n SwapNamespaceImpl,\n} from '@/shared/core/swap-namespace';\nimport type { Config } from '@/shared/types/config';\nimport type {\n DocumentSubmission,\n DocumentType,\n} from '@/shared/types/document-submission';\nimport type { OAuthSessionDto } from '@/shared/types/dto/oauth-session';\nimport { NotAuthenticatedError } from '@/shared/types/errors';\nimport type { KycLevelName, KycToken } from '@/shared/types/kyc';\nimport type {\n AuthorizationCode,\n ClientSecret,\n CodeVerifier,\n} from '@/shared/types/oauth';\nimport {\n ClientCredentialsOAuth,\n type OAuthAccessToken,\n type OAuthRefreshToken,\n OAuthSession,\n} from '@/shared/types/oauth-session';\nimport type { Offer, OfferId } from '@/shared/types/offer';\nimport type { OfferDetail, OfferOptionId } from '@/shared/types/offer-detail';\nimport type {\n ConnectExternalWalletParams,\n OfferOptionAddress,\n OfferOptionAddressId,\n} from '@/shared/types/offer-option-address';\nimport type {\n CreateParticipationParams,\n Participation,\n ParticipationId,\n ParticipationsPaginationParams,\n} from '@/shared/types/participation';\nimport type { Pii } from '@/shared/types/pii';\nimport type {\n Requirement,\n RequirementStatusInfo,\n} from '@/shared/types/requirement';\nimport type {\n CreateWalletOwnershipChallengeParams,\n WalletOwnershipChallenge,\n} from '@/shared/types/wallet-ownership-challenge';\n\n/** Buffer in seconds before expiry to consider token expired for refresh. */\nconst ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS = 60;\n\nexport interface SessionStore {\n getSession(): Promise<OAuthSession | null>;\n /**\n * Persists or clears the OAuth session.\n *\n * **Omit this method to create a read-only store.** When absent, the SDK\n * skips token refresh entirely — no network call is made and no refresh\n * token is consumed. This is the correct approach for contexts that can read\n * the session but cannot write it back, such as Next.js Server Components.\n *\n * ⚠️ Do **not** implement this as a no-op (`async () => {}`). If the method\n * is present, the SDK assumes writes succeed: it will fire a token refresh\n * network call, consume the refresh token, then invoke `setSession` — which\n * would silently discard the new session and leave the browser holding an\n * invalidated refresh token. Simply **omit** `setSession` to prevent any\n * refresh from being attempted.\n *\n * {@link CoinListServer.completeOAuth} and {@link CoinListServer.logout}\n * always require a writable store and throw\n * {@link WritableSessionStoreRequiredError} if `setSession` is absent.\n */\n setSession?(session: OAuthSession | null): Promise<void>;\n}\n\nexport interface ServerConfig extends Config {\n readonly clientSecret: ClientSecret;\n readonly sessionStore: SessionStore;\n /** Buffer in seconds before expiry to consider token expired for refresh. */\n readonly accessTokenExpiryBufferSeconds?: number;\n /**\n * Whether SDK will throw an exception in cases it can be silent.\n * For example, if token revokation on logout fails.\n */\n readonly strict?: boolean;\n}\n\n/**\n * Server-side CoinList SDK client.\n *\n * Operates in one of two modes depending on whether {@link SessionStore}\n * includes a `setSession` implementation:\n *\n * - **Writable store** (`setSession` provided) — full functionality: token\n * refresh, {@link completeOAuth}, and {@link logout} all work normally.\n *\n * - **Read-only store** (no `setSession`) — token refresh is skipped entirely,\n * meaning no network call is made and no refresh token is consumed.\n * {@link completeOAuth} and {@link logout} throw\n * {@link WritableSessionStoreRequiredError}. {@link accessToken} may return\n * an expired token (see its docs). Use this mode in execution contexts that\n * can read the session but cannot write it back, such as Next.js Server\n * Components.\n */\nexport interface CoinListServer {\n /**\n * Exchanges an authorization code for an OAuth session and persists it via\n * {@link SessionStore.setSession}.\n *\n * Throws {@link WritableSessionStoreRequiredError} if the session store does\n * not provide `setSession`.\n */\n completeOAuth(\n code: AuthorizationCode,\n codeVerifier: CodeVerifier\n ): Promise<OAuthSession>;\n\n /**\n * Obtains an app-level access token via the OAuth 2.0 `client_credentials`\n * grant (RFC 6749 §4.4). No user is involved: the token authenticates the\n * partner application itself and only grants access to app-level resources\n * such as offers and offer requirements.\n *\n * The token is **not** persisted to the {@link SessionStore} and has no\n * refresh token. It expires at `expiresAt`; once expired, call this method\n * again to obtain a fresh token — the SDK does not renew it automatically.\n *\n * Pass the result to {@link fetchOffers}, {@link fetchOffersPage},\n * {@link fetchOfferDetails}, or {@link fetchOfferRequirements} to call them\n * without a user session.\n */\n clientCredentialsOAuth(): Promise<ClientCredentialsOAuth>;\n\n /**\n * Returns a valid access token for the current session, refreshing it if\n * it is expired or near expiry.\n *\n * **Writable store**: if the token is expired, the SDK exchanges the refresh\n * token for a new session, persists it, and returns the fresh access token.\n * Returns `null` if there is no session or the refresh fails.\n *\n * **Read-only store** (no `setSession`): refresh is skipped entirely. The\n * stored token is returned as-is, even if it is expired — a non-null return\n * value does **not** guarantee the token is accepted by the API. Before\n * making API calls, check `token.expiresAt > new Date()`. Use a writable\n * store (e.g. in a Route Handler) when you need the SDK to renew the session\n * automatically.\n *\n * @returns the access token, or `null` if there is no session or the session\n * could not be refreshed.\n */\n accessToken(): Promise<OAuthAccessToken | null>;\n\n /**\n * Revokes the current token via POST /oauth/revoke and clears the session.\n *\n * Throws {@link WritableSessionStoreRequiredError} if the session store does\n * not provide `setSession`.\n */\n logout(): Promise<void>;\n\n /**\n * Fetches all offers by iterating through every paginated response.\n *\n * @param clientCreds optional app-level token from\n * {@link clientCredentialsOAuth}. When provided, no user session is\n * required; if a user session exists it takes precedence and `clientCreds`\n * is used as a fallback.\n *\n * Throws {@link NotAuthenticatedError} if there is neither a user session\n * nor `clientCreds`.\n */\n fetchOffers(clientCreds?: ClientCredentialsOAuth): Promise<Offer[]>;\n\n /**\n * Fetches a single page of offers.\n *\n * @param clientCreds optional app-level token from\n * {@link clientCredentialsOAuth}. When provided, no user session is\n * required; if a user session exists it takes precedence and `clientCreds`\n * is used as a fallback.\n *\n * Throws {@link NotAuthenticatedError} if there is neither a user session\n * nor `clientCreds`.\n */\n fetchOffersPage(\n params: PaginationParams,\n clientCreds?: ClientCredentialsOAuth\n ): Promise<PaginatedResponse<Offer>>;\n\n /**\n * Fetches details for a given offer by its id.\n *\n * @param clientCreds optional app-level token from\n * {@link clientCredentialsOAuth}. When provided, no user session is\n * required; if a user session exists it takes precedence and `clientCreds`\n * is used as a fallback.\n *\n * Throws {@link NotAuthenticatedError} if there is neither a user session\n * nor `clientCreds`.\n */\n fetchOfferDetails(\n id: OfferId,\n clientCreds?: ClientCredentialsOAuth\n ): Promise<OfferDetail>;\n\n /**\n * Fetches all participations by iterating through every paginated response.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchParticipations(offerId?: OfferId): Promise<Participation[]>;\n\n /**\n * Fetches a single page of participations, optionally filtered by offer.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchParticipationsPage(\n params: ParticipationsPaginationParams\n ): Promise<PaginatedResponse<Participation>>;\n\n /**\n * Fetches a participation by id.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchParticipation(id: ParticipationId): Promise<Participation>;\n\n /**\n * Creates a participation.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n createParticipation(\n params: CreateParticipationParams\n ): Promise<Participation>;\n\n /**\n * Creates a single-use wallet-ownership challenge for the given wallet and\n * chain. The user signs the returned {@link WalletOwnershipChallenge.message}\n * with their wallet, then passes the signature to\n * {@link connectExternalWallet}.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n createWalletOwnershipChallenge(\n params: CreateWalletOwnershipChallengeParams\n ): Promise<WalletOwnershipChallenge>;\n\n /**\n * Connects a proven external wallet to an offer option, using a signature of\n * a challenge from {@link createWalletOwnershipChallenge}.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n connectExternalWallet(\n offerId: OfferId,\n params: ConnectExternalWalletParams\n ): Promise<OfferOptionAddress>;\n\n /**\n * Lists the user's proven wallet bindings for a single offer option.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n listOptionAddresses(\n offerId: OfferId,\n offerOptionId: OfferOptionId\n ): Promise<OfferOptionAddress[]>;\n\n /**\n * Removes one of the user's wallet bindings and returns the removed binding.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n removeOptionAddress(\n offerId: OfferId,\n addressId: OfferOptionAddressId\n ): Promise<OfferOptionAddress>;\n\n /**\n * Fetches the requirements for all options of a given offer, grouped by option ID.\n *\n * @param clientCreds optional app-level token from\n * {@link clientCredentialsOAuth}. When provided, no user session is\n * required; if a user session exists it takes precedence and `clientCreds`\n * is used as a fallback.\n *\n * Throws {@link NotAuthenticatedError} if there is neither a user session\n * nor `clientCreds`.\n */\n fetchOfferRequirements(\n offerId: OfferId,\n clientCreds?: ClientCredentialsOAuth\n ): Promise<Record<OfferOptionId, Requirement[]>>;\n\n /**\n * Fetches the user's requirement statuses for a given offer.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchRequirementStatuses(offerId: OfferId): Promise<RequirementStatusInfo[]>;\n\n /**\n * Fetches the user's PII (tax form pre-fill data) — full legal name, date\n * of birth, jurisdiction, tax ID, and permanent address for an individual;\n * or the equivalent entity fields for a company/trust, used to pre-fill a\n * W-8BEN. Fields the entity hasn't provided are `null`.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n fetchPii(): Promise<Pii>;\n\n /**\n * Starts (or resumes) a document signing submission for the given type\n * (currently only `tax_certification`, e.g. W-8BEN/W-8BEN-E). `fields` are\n * signing-form values keyed by the document's DocuSeal field names,\n * forwarded verbatim to Passport to pre-fill the document.\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n submitDocument(\n documentType: DocumentType,\n fields: Record<string, string>\n ): Promise<DocumentSubmission>;\n\n /**\n * On-chain swap operations: quoting a swap, reading swap-contract state and\n * token allowances, and proving/allow-listing wallet ownership — e.g.\n * `coinlist.swap.getOutputToken({ contractAddress, chain })`.\n *\n * These methods require a user session and throw\n * {@link NotAuthenticatedError} if the user is not authenticated.\n */\n readonly swap: CoinListSwapNamespace;\n\n /**\n * Creates a short-lived Sumsub WebSDK access token for the current user so\n * an identity verification (KYC) flow can be started, e.g. to seed the\n * client-side `IdentityVerification` component when server-rendering.\n * `levelName` selects the Sumsub verification level; defaults to the\n * backend's standard level. `reset` resets the Sumsub applicant first, so\n * an already-approved level can be executed again (e.g. to update stale\n * PII).\n *\n * Throws {@link NotAuthenticatedError} if the user is not authenticated.\n */\n createKycToken(levelName?: KycLevelName, reset?: boolean): Promise<KycToken>;\n}\n\nclass CoinListServerImpl implements CoinListServer {\n private readonly api: Api;\n private readonly baseUrl: string;\n\n private readonly accessTokenExpiryBufferSeconds: number;\n private readonly strict: boolean;\n readonly swap: CoinListSwapNamespace;\n\n constructor(private readonly _config: ServerConfig) {\n this.baseUrl = _config.baseUrl ?? PUBLIC_API_BASE_URL;\n this.accessTokenExpiryBufferSeconds =\n _config.accessTokenExpiryBufferSeconds ??\n ACCESS_TOKEN_EXPIRY_BUFFER_SECONDS;\n this.strict = _config.strict ?? false;\n this.api = new Api(\n {\n baseUrl: this.baseUrl,\n xApiVersion: API_VERSION,\n },\n // When refresh=true the renewal middleware has received a 401 and wants a\n // fresh token. A read-only store cannot persist a new session, so return\n // null immediately — this tells the middleware to skip the retry rather\n // than re-sending with the same expired token and wasting a round-trip.\n (refresh) =>\n refresh && !this._config.sessionStore.setSession\n ? Promise.resolve(null)\n : this.accessToken()\n );\n this.swap = new SwapNamespaceImpl({\n api: this.api,\n ensureUserAuthenticated: () => this.ensureUserAuthenticated(),\n });\n }\n\n async completeOAuth(\n code: AuthorizationCode,\n codeVerifier: CodeVerifier\n ): Promise<OAuthSession> {\n const sessionStore = this._config.sessionStore;\n const setSession = sessionStore.setSession?.bind(sessionStore);\n if (!setSession) {\n throw new WritableSessionStoreRequiredError();\n }\n const sessionDto = await this.api.send<OAuthSessionDto>({\n method: 'POST',\n url: `/oauth/token`,\n body: {\n grant_type: 'authorization_code',\n code,\n redirect_uri: this._config.redirectUri,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n code_verifier: codeVerifier,\n },\n });\n const session = OAuthSession.fromDto(sessionDto);\n await setSession(session);\n return session;\n }\n\n async clientCredentialsOAuth(): Promise<ClientCredentialsOAuth> {\n const sessionDto = await this.api.send<OAuthSessionDto>({\n method: 'POST',\n url: `/oauth/token`,\n body: {\n grant_type: 'client_credentials',\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n },\n });\n const session = OAuthSession.fromDto(sessionDto);\n return ClientCredentialsOAuth(session.accessToken);\n }\n\n async accessToken(): Promise<OAuthAccessToken | null> {\n const sessionStore = this._config.sessionStore;\n const session = await sessionStore.getSession();\n if (session == null) return null;\n\n const now = Date.now();\n const expiresAt = session.accessToken.expiresAt.getTime();\n const bufferMs = this.accessTokenExpiryBufferSeconds * 1000;\n if (expiresAt > now + bufferMs) {\n // Valid access token, return it regardless\n return session.accessToken;\n }\n\n const setSession = sessionStore.setSession?.bind(sessionStore);\n if (!setSession) {\n // No write session capabilities => can't refresh!\n // Return the access token as-is\n return session.accessToken;\n } else {\n return this.refreshSession(session.refreshToken, setSession);\n }\n }\n\n private async refreshSession(\n refreshToken: OAuthRefreshToken | undefined,\n setSession: (session: OAuthSession | null) => Promise<void>\n ): Promise<OAuthAccessToken | null> {\n if (!refreshToken) {\n await setSession(null);\n return null;\n }\n\n try {\n const sessionDto = await this.api.send<OAuthSessionDto>({\n method: 'POST',\n url: `/oauth/token`,\n body: {\n grant_type: 'refresh_token',\n refresh_token: refreshToken,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n },\n });\n const newSession = OAuthSession.fromDto(sessionDto);\n await setSession(newSession);\n return newSession.accessToken;\n } catch {\n await setSession(null);\n return null;\n }\n }\n\n async logout(): Promise<void> {\n const sessionStore = this._config.sessionStore;\n const setSession = sessionStore.setSession?.bind(sessionStore);\n if (!setSession) {\n throw new WritableSessionStoreRequiredError();\n }\n const session = await sessionStore.getSession();\n if (session != null) {\n const tokenToRevoke = session.accessToken.value;\n try {\n await this.api.send({\n method: 'POST',\n url: `/oauth/revoke`,\n body: {\n token: tokenToRevoke,\n client_id: this._config.clientId,\n client_secret: this._config.clientSecret,\n },\n });\n } catch (err) {\n if (err instanceof HttpError) {\n if (this.strict) {\n throw err;\n }\n } else {\n throw err;\n }\n }\n // invalidate the session\n await setSession(null);\n }\n }\n\n async fetchOffers(clientCreds?: ClientCredentialsOAuth): Promise<Offer[]> {\n await this.ensureAuthenticated(clientCreds);\n return offersApi.fetchOffers(this.api, clientCreds);\n }\n\n async fetchOffersPage(\n params: PaginationParams,\n clientCreds?: ClientCredentialsOAuth\n ): Promise<PaginatedResponse<Offer>> {\n await this.ensureAuthenticated(clientCreds);\n return offersApi.fetchOffersPage(this.api, params, clientCreds);\n }\n\n async fetchOfferDetails(\n id: OfferId,\n clientCreds?: ClientCredentialsOAuth\n ): Promise<OfferDetail> {\n await this.ensureAuthenticated(clientCreds);\n return offersApi.fetchOfferDetails(this.api, id, clientCreds);\n }\n\n async fetchParticipations(offerId?: OfferId): Promise<Participation[]> {\n await this.ensureUserAuthenticated();\n return participationsApi.fetchParticipations(this.api, offerId);\n }\n\n async fetchParticipationsPage(\n params: ParticipationsPaginationParams\n ): Promise<PaginatedResponse<Participation>> {\n await this.ensureUserAuthenticated();\n return participationsApi.fetchParticipationsPage(this.api, params);\n }\n\n async fetchParticipation(id: ParticipationId): Promise<Participation> {\n await this.ensureUserAuthenticated();\n return participationsApi.fetchParticipation(this.api, id);\n }\n\n async createParticipation(\n params: CreateParticipationParams\n ): Promise<Participation> {\n await this.ensureUserAuthenticated();\n return participationsApi.createParticipation(this.api, params);\n }\n\n async createWalletOwnershipChallenge(\n params: CreateWalletOwnershipChallengeParams\n ): Promise<WalletOwnershipChallenge> {\n await this.ensureUserAuthenticated();\n return walletConnectApi.createWalletOwnershipChallenge(this.api, params);\n }\n\n async connectExternalWallet(\n offerId: OfferId,\n params: ConnectExternalWalletParams\n ): Promise<OfferOptionAddress> {\n await this.ensureUserAuthenticated();\n return walletConnectApi.connectExternalWallet(this.api, offerId, params);\n }\n\n async listOptionAddresses(\n offerId: OfferId,\n offerOptionId: OfferOptionId\n ): Promise<OfferOptionAddress[]> {\n await this.ensureUserAuthenticated();\n return walletConnectApi.listOptionAddresses(\n this.api,\n offerId,\n offerOptionId\n );\n }\n\n async removeOptionAddress(\n offerId: OfferId,\n addressId: OfferOptionAddressId\n ): Promise<OfferOptionAddress> {\n await this.ensureUserAuthenticated();\n return walletConnectApi.removeOptionAddress(this.api, offerId, addressId);\n }\n\n async fetchOfferRequirements(\n offerId: OfferId,\n clientCreds?: ClientCredentialsOAuth\n ): Promise<Record<OfferOptionId, Requirement[]>> {\n await this.ensureAuthenticated(clientCreds);\n return requirementsApi.fetchOfferRequirements(\n this.api,\n offerId,\n clientCreds\n );\n }\n\n async fetchRequirementStatuses(\n offerId: OfferId\n ): Promise<RequirementStatusInfo[]> {\n await this.ensureUserAuthenticated();\n return requirementsApi.fetchRequirementStatuses(this.api, offerId);\n }\n\n private async ensureAuthenticated(\n clientCreds: ClientCredentialsOAuth | undefined\n ): Promise<void> {\n if (!clientCreds) {\n await this.ensureUserAuthenticated();\n }\n }\n\n private async ensureUserAuthenticated(): Promise<void> {\n const token = await this.accessToken();\n if (token === null) {\n throw new NotAuthenticatedError();\n }\n }\n\n async fetchPii(): Promise<Pii> {\n await this.ensureUserAuthenticated();\n return piiApi.fetchPii(this.api);\n }\n\n async submitDocument(\n documentType: DocumentType,\n fields: Record<string, string>\n ): Promise<DocumentSubmission> {\n await this.ensureUserAuthenticated();\n return documentsApi.submitDocument(this.api, documentType, fields);\n }\n\n async createKycToken(\n levelName?: KycLevelName,\n reset?: boolean\n ): Promise<KycToken> {\n await this.ensureUserAuthenticated();\n return kycApi.createKycToken(this.api, levelName, reset);\n }\n}\n\nexport function createCoinListServer(config: ServerConfig): CoinListServer {\n return new CoinListServerImpl(config);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIO,IAAM,MAAN,MAAU;AAAA,EAGf,YACE,QACA,kBACA;AACA,SAAK,SAAS,IAAI,uBAAuB,QAAQ,gBAAgB;AAAA,EACnE;AAAA,EAEA,MAAM,KAAgB,SAA0C;AAC9D,WAAO,KAAK,OAAO,KAAgB,OAAO;AAAA,EAC5C;AACF;;;ACjBO,IAAM,oCAAN,cAAgD,MAAM;AAAA,EAC3D,YACE,UAAU,mJACV;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;AC0DA,IAAM,qCAAqC;AA8S3C,IAAM,qBAAN,MAAmD;AAAA,EAQjD,YAA6B,SAAuB;AAAvB;AAC3B,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,iCACH,QAAQ,kCACR;AACF,SAAK,SAAS,QAAQ,UAAU;AAChC,SAAK,MAAM,IAAI;AAAA,MACb;AAAA,QACE,SAAS,KAAK;AAAA,QACd,aAAa;AAAA,MACf;AAAA;AAAA;AAAA;AAAA;AAAA,MAKA,CAAC,YACC,WAAW,CAAC,KAAK,QAAQ,aAAa,aAClC,QAAQ,QAAQ,IAAI,IACpB,KAAK,YAAY;AAAA,IACzB;AACA,SAAK,OAAO,IAAI,kBAAkB;AAAA,MAChC,KAAK,KAAK;AAAA,MACV,yBAAyB,MAAM,KAAK,wBAAwB;AAAA,IAC9D,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,cACJ,MACA,cACuB;AACvB,UAAM,eAAe,KAAK,QAAQ;AAClC,UAAM,aAAa,aAAa,YAAY,KAAK,YAAY;AAC7D,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,kCAAkC;AAAA,IAC9C;AACA,UAAM,aAAa,MAAM,KAAK,IAAI,KAAsB;AAAA,MACtD,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,MAAM;AAAA,QACJ,YAAY;AAAA,QACZ;AAAA,QACA,cAAc,KAAK,QAAQ;AAAA,QAC3B,WAAW,KAAK,QAAQ;AAAA,QACxB,eAAe,KAAK,QAAQ;AAAA,QAC5B,eAAe;AAAA,MACjB;AAAA,IACF,CAAC;AACD,UAAM,UAAU,aAAa,QAAQ,UAAU;AAC/C,UAAM,WAAW,OAAO;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,yBAA0D;AAC9D,UAAM,aAAa,MAAM,KAAK,IAAI,KAAsB;AAAA,MACtD,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,MAAM;AAAA,QACJ,YAAY;AAAA,QACZ,WAAW,KAAK,QAAQ;AAAA,QACxB,eAAe,KAAK,QAAQ;AAAA,MAC9B;AAAA,IACF,CAAC;AACD,UAAM,UAAU,aAAa,QAAQ,UAAU;AAC/C,WAAO,uBAAuB,QAAQ,WAAW;AAAA,EACnD;AAAA,EAEA,MAAM,cAAgD;AACpD,UAAM,eAAe,KAAK,QAAQ;AAClC,UAAM,UAAU,MAAM,aAAa,WAAW;AAC9C,QAAI,WAAW,KAAM,QAAO;AAE5B,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,YAAY,QAAQ,YAAY,UAAU,QAAQ;AACxD,UAAM,WAAW,KAAK,iCAAiC;AACvD,QAAI,YAAY,MAAM,UAAU;AAE9B,aAAO,QAAQ;AAAA,IACjB;AAEA,UAAM,aAAa,aAAa,YAAY,KAAK,YAAY;AAC7D,QAAI,CAAC,YAAY;AAGf,aAAO,QAAQ;AAAA,IACjB,OAAO;AACL,aAAO,KAAK,eAAe,QAAQ,cAAc,UAAU;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,MAAc,eACZ,cACA,YACkC;AAClC,QAAI,CAAC,cAAc;AACjB,YAAM,WAAW,IAAI;AACrB,aAAO;AAAA,IACT;AAEA,QAAI;AACF,YAAM,aAAa,MAAM,KAAK,IAAI,KAAsB;AAAA,QACtD,QAAQ;AAAA,QACR,KAAK;AAAA,QACL,MAAM;AAAA,UACJ,YAAY;AAAA,UACZ,eAAe;AAAA,UACf,WAAW,KAAK,QAAQ;AAAA,UACxB,eAAe,KAAK,QAAQ;AAAA,QAC9B;AAAA,MACF,CAAC;AACD,YAAM,aAAa,aAAa,QAAQ,UAAU;AAClD,YAAM,WAAW,UAAU;AAC3B,aAAO,WAAW;AAAA,IACpB,QAAQ;AACN,YAAM,WAAW,IAAI;AACrB,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,SAAwB;AAC5B,UAAM,eAAe,KAAK,QAAQ;AAClC,UAAM,aAAa,aAAa,YAAY,KAAK,YAAY;AAC7D,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,kCAAkC;AAAA,IAC9C;AACA,UAAM,UAAU,MAAM,aAAa,WAAW;AAC9C,QAAI,WAAW,MAAM;AACnB,YAAM,gBAAgB,QAAQ,YAAY;AAC1C,UAAI;AACF,cAAM,KAAK,IAAI,KAAK;AAAA,UAClB,QAAQ;AAAA,UACR,KAAK;AAAA,UACL,MAAM;AAAA,YACJ,OAAO;AAAA,YACP,WAAW,KAAK,QAAQ;AAAA,YACxB,eAAe,KAAK,QAAQ;AAAA,UAC9B;AAAA,QACF,CAAC;AAAA,MACH,SAAS,KAAK;AACZ,YAAI,eAAe,WAAW;AAC5B,cAAI,KAAK,QAAQ;AACf,kBAAM;AAAA,UACR;AAAA,QACF,OAAO;AACL,gBAAM;AAAA,QACR;AAAA,MACF;AAEA,YAAM,WAAW,IAAI;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,aAAwD;AACxE,UAAM,KAAK,oBAAoB,WAAW;AAC1C,WAAiB,YAAY,KAAK,KAAK,WAAW;AAAA,EACpD;AAAA,EAEA,MAAM,gBACJ,QACA,aACmC;AACnC,UAAM,KAAK,oBAAoB,WAAW;AAC1C,WAAiB,gBAAgB,KAAK,KAAK,QAAQ,WAAW;AAAA,EAChE;AAAA,EAEA,MAAM,kBACJ,IACA,aACsB;AACtB,UAAM,KAAK,oBAAoB,WAAW;AAC1C,WAAiB,kBAAkB,KAAK,KAAK,IAAI,WAAW;AAAA,EAC9D;AAAA,EAEA,MAAM,oBAAoB,SAA6C;AACrE,UAAM,KAAK,wBAAwB;AACnC,WAAyB,oBAAoB,KAAK,KAAK,OAAO;AAAA,EAChE;AAAA,EAEA,MAAM,wBACJ,QAC2C;AAC3C,UAAM,KAAK,wBAAwB;AACnC,WAAyB,wBAAwB,KAAK,KAAK,MAAM;AAAA,EACnE;AAAA,EAEA,MAAM,mBAAmB,IAA6C;AACpE,UAAM,KAAK,wBAAwB;AACnC,WAAyB,mBAAmB,KAAK,KAAK,EAAE;AAAA,EAC1D;AAAA,EAEA,MAAM,oBACJ,QACwB;AACxB,UAAM,KAAK,wBAAwB;AACnC,WAAyB,oBAAoB,KAAK,KAAK,MAAM;AAAA,EAC/D;AAAA,EAEA,MAAM,+BACJ,QACmC;AACnC,UAAM,KAAK,wBAAwB;AACnC,WAAwB,+BAA+B,KAAK,KAAK,MAAM;AAAA,EACzE;AAAA,EAEA,MAAM,sBACJ,SACA,QAC6B;AAC7B,UAAM,KAAK,wBAAwB;AACnC,WAAwB,sBAAsB,KAAK,KAAK,SAAS,MAAM;AAAA,EACzE;AAAA,EAEA,MAAM,oBACJ,SACA,eAC+B;AAC/B,UAAM,KAAK,wBAAwB;AACnC,WAAwB;AAAA,MACtB,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,oBACJ,SACA,WAC6B;AAC7B,UAAM,KAAK,wBAAwB;AACnC,WAAwB,oBAAoB,KAAK,KAAK,SAAS,SAAS;AAAA,EAC1E;AAAA,EAEA,MAAM,uBACJ,SACA,aAC+C;AAC/C,UAAM,KAAK,oBAAoB,WAAW;AAC1C,WAAuB;AAAA,MACrB,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,yBACJ,SACkC;AAClC,UAAM,KAAK,wBAAwB;AACnC,WAAuB,yBAAyB,KAAK,KAAK,OAAO;AAAA,EACnE;AAAA,EAEA,MAAc,oBACZ,aACe;AACf,QAAI,CAAC,aAAa;AAChB,YAAM,KAAK,wBAAwB;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,MAAc,0BAAyC;AACrD,UAAM,QAAQ,MAAM,KAAK,YAAY;AACrC,QAAI,UAAU,MAAM;AAClB,YAAM,IAAI,sBAAsB;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,MAAM,WAAyB;AAC7B,UAAM,KAAK,wBAAwB;AACnC,WAAc,SAAS,KAAK,GAAG;AAAA,EACjC;AAAA,EAEA,MAAM,eACJ,cACA,QAC6B;AAC7B,UAAM,KAAK,wBAAwB;AACnC,WAAoB,eAAe,KAAK,KAAK,cAAc,MAAM;AAAA,EACnE;AAAA,EAEA,MAAM,eACJ,WACA,OACmB;AACnB,UAAM,KAAK,wBAAwB;AACnC,WAAc,eAAe,KAAK,KAAK,WAAW,KAAK;AAAA,EACzD;AACF;AAEO,SAAS,qBAAqB,QAAsC;AACzE,SAAO,IAAI,mBAAmB,MAAM;AACtC;","names":[]}
|