@coinlist-co/react 0.9.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/{chunk-I5YTJ5SL.js → chunk-AQVCOWOV.js} +163 -69
  2. package/dist/chunk-AQVCOWOV.js.map +1 -0
  3. package/dist/{chunk-MKCOK3DF.js → chunk-TBU3EBNM.js} +2 -43
  4. package/dist/chunk-TBU3EBNM.js.map +1 -0
  5. package/dist/{chunk-Z2HAA2TI.js → chunk-UOHD7US2.js} +150 -63
  6. package/dist/chunk-UOHD7US2.js.map +1 -0
  7. package/dist/client/index.cjs +415 -292
  8. package/dist/client/index.cjs.map +1 -1
  9. package/dist/client/index.d.cts +131 -49
  10. package/dist/client/index.d.ts +131 -49
  11. package/dist/client/index.js +169 -76
  12. package/dist/client/index.js.map +1 -1
  13. package/dist/{collections-BQbFJS3g.d.ts → collections-Bv1Oxzu_.d.ts} +1 -1
  14. package/dist/{collections-B84Vw55t.d.cts → collections-DDyxbOPZ.d.cts} +1 -1
  15. package/dist/{requirement-C2w45Q11.d.cts → requirement-oVZA1INj.d.cts} +271 -200
  16. package/dist/{requirement-C2w45Q11.d.ts → requirement-oVZA1INj.d.ts} +271 -200
  17. package/dist/server/index.cjs +135 -116
  18. package/dist/server/index.cjs.map +1 -1
  19. package/dist/server/index.d.cts +20 -27
  20. package/dist/server/index.d.ts +20 -27
  21. package/dist/server/index.js +10 -27
  22. package/dist/server/index.js.map +1 -1
  23. package/dist/shared/index.cjs +145 -75
  24. package/dist/shared/index.cjs.map +1 -1
  25. package/dist/shared/index.d.cts +4 -4
  26. package/dist/shared/index.d.ts +4 -4
  27. package/dist/shared/index.js +16 -92
  28. package/dist/shared/index.js.map +1 -1
  29. package/package.json +1 -1
  30. package/dist/chunk-AAER5LOL.js +0 -22
  31. package/dist/chunk-AAER5LOL.js.map +0 -1
  32. package/dist/chunk-I5YTJ5SL.js.map +0 -1
  33. package/dist/chunk-MKCOK3DF.js.map +0 -1
  34. package/dist/chunk-Z2HAA2TI.js.map +0 -1
@@ -1,4 +1,4 @@
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';
1
+ import { h as AuthorizationCode, i as CodeVerifier, I as OAuthSession, J as ClientCredentialsOAuth, k as OAuthAccessToken, l as Offer, m as PaginationParams, n as PaginatedResponse, O as OfferId, o as OfferDetail, p as CreateWalletOwnershipChallengeParams, W as WalletOwnershipChallenge, q as ConnectExternalWalletParams, r as OfferOptionAddress, g as OfferOptionId, s as OfferOptionAddressId, R as Requirement, t as RequirementStatusInfo, u as Pii, D as DocumentType, v as DocumentSubmission, c as CoinListErc20Namespace, f as CoinListTokenSaleNamespace, C as CoinListSwapNamespace, K as KycLevelName, w as KycToken, j as Config, L as ClientSecret } from '../requirement-oVZA1INj.cjs';
2
2
  import 'viem';
3
3
 
4
4
  interface SessionStore {
@@ -138,30 +138,6 @@ interface CoinListServer {
138
138
  * nor `clientCreds`.
139
139
  */
140
140
  fetchOfferDetails(id: OfferId, clientCreds?: ClientCredentialsOAuth): Promise<OfferDetail>;
141
- /**
142
- * Fetches all participations by iterating through every paginated response.
143
- *
144
- * Throws {@link NotAuthenticatedError} if the user is not authenticated.
145
- */
146
- fetchParticipations(offerId?: OfferId): Promise<Participation[]>;
147
- /**
148
- * Fetches a single page of participations, optionally filtered by offer.
149
- *
150
- * Throws {@link NotAuthenticatedError} if the user is not authenticated.
151
- */
152
- fetchParticipationsPage(params: ParticipationsPaginationParams): Promise<PaginatedResponse<Participation>>;
153
- /**
154
- * Fetches a participation by id.
155
- *
156
- * Throws {@link NotAuthenticatedError} if the user is not authenticated.
157
- */
158
- fetchParticipation(id: ParticipationId): Promise<Participation>;
159
- /**
160
- * Creates a participation.
161
- *
162
- * Throws {@link NotAuthenticatedError} if the user is not authenticated.
163
- */
164
- createParticipation(params: CreateParticipationParams): Promise<Participation>;
165
141
  /**
166
142
  * Creates a single-use wallet-ownership challenge for the given wallet and
167
143
  * chain. The user signs the returned {@link WalletOwnershipChallenge.message}
@@ -227,8 +203,25 @@ interface CoinListServer {
227
203
  */
228
204
  submitDocument(documentType: DocumentType, fields: Record<string, string>): Promise<DocumentSubmission>;
229
205
  /**
230
- * On-chain swap operations: quoting a swap, reading swap-contract state and
231
- * token allowances, and proving/allow-listing wallet ownership — e.g.
206
+ * Generic ERC-20 reads (token allowance and balance) — e.g.
207
+ * `coinlist.erc20.getTokenBalance({ ... })`.
208
+ *
209
+ * These methods require a user session and throw
210
+ * {@link NotAuthenticatedError} if the user is not authenticated.
211
+ */
212
+ readonly erc20: CoinListErc20Namespace;
213
+ /**
214
+ * Token-sale operations: listing, reading, and recording participations —
215
+ * e.g. `coinlist.tokenSale.fetchParticipations()`. The on-chain
216
+ * `executeTokenSale` flow is client-only and is not exposed here.
217
+ *
218
+ * These methods require a user session and throw
219
+ * {@link NotAuthenticatedError} if the user is not authenticated.
220
+ */
221
+ readonly tokenSale: CoinListTokenSaleNamespace;
222
+ /**
223
+ * On-chain swap operations: quoting a swap, reading swap-contract state, and
224
+ * proving/allow-listing wallet ownership — e.g.
232
225
  * `coinlist.swap.getOutputToken({ contractAddress, chain })`.
233
226
  *
234
227
  * These methods require a user session and throw
@@ -1,4 +1,4 @@
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';
1
+ import { h as AuthorizationCode, i as CodeVerifier, I as OAuthSession, J as ClientCredentialsOAuth, k as OAuthAccessToken, l as Offer, m as PaginationParams, n as PaginatedResponse, O as OfferId, o as OfferDetail, p as CreateWalletOwnershipChallengeParams, W as WalletOwnershipChallenge, q as ConnectExternalWalletParams, r as OfferOptionAddress, g as OfferOptionId, s as OfferOptionAddressId, R as Requirement, t as RequirementStatusInfo, u as Pii, D as DocumentType, v as DocumentSubmission, c as CoinListErc20Namespace, f as CoinListTokenSaleNamespace, C as CoinListSwapNamespace, K as KycLevelName, w as KycToken, j as Config, L as ClientSecret } from '../requirement-oVZA1INj.js';
2
2
  import 'viem';
3
3
 
4
4
  interface SessionStore {
@@ -138,30 +138,6 @@ interface CoinListServer {
138
138
  * nor `clientCreds`.
139
139
  */
140
140
  fetchOfferDetails(id: OfferId, clientCreds?: ClientCredentialsOAuth): Promise<OfferDetail>;
141
- /**
142
- * Fetches all participations by iterating through every paginated response.
143
- *
144
- * Throws {@link NotAuthenticatedError} if the user is not authenticated.
145
- */
146
- fetchParticipations(offerId?: OfferId): Promise<Participation[]>;
147
- /**
148
- * Fetches a single page of participations, optionally filtered by offer.
149
- *
150
- * Throws {@link NotAuthenticatedError} if the user is not authenticated.
151
- */
152
- fetchParticipationsPage(params: ParticipationsPaginationParams): Promise<PaginatedResponse<Participation>>;
153
- /**
154
- * Fetches a participation by id.
155
- *
156
- * Throws {@link NotAuthenticatedError} if the user is not authenticated.
157
- */
158
- fetchParticipation(id: ParticipationId): Promise<Participation>;
159
- /**
160
- * Creates a participation.
161
- *
162
- * Throws {@link NotAuthenticatedError} if the user is not authenticated.
163
- */
164
- createParticipation(params: CreateParticipationParams): Promise<Participation>;
165
141
  /**
166
142
  * Creates a single-use wallet-ownership challenge for the given wallet and
167
143
  * chain. The user signs the returned {@link WalletOwnershipChallenge.message}
@@ -227,8 +203,25 @@ interface CoinListServer {
227
203
  */
228
204
  submitDocument(documentType: DocumentType, fields: Record<string, string>): Promise<DocumentSubmission>;
229
205
  /**
230
- * On-chain swap operations: quoting a swap, reading swap-contract state and
231
- * token allowances, and proving/allow-listing wallet ownership — e.g.
206
+ * Generic ERC-20 reads (token allowance and balance) — e.g.
207
+ * `coinlist.erc20.getTokenBalance({ ... })`.
208
+ *
209
+ * These methods require a user session and throw
210
+ * {@link NotAuthenticatedError} if the user is not authenticated.
211
+ */
212
+ readonly erc20: CoinListErc20Namespace;
213
+ /**
214
+ * Token-sale operations: listing, reading, and recording participations —
215
+ * e.g. `coinlist.tokenSale.fetchParticipations()`. The on-chain
216
+ * `executeTokenSale` flow is client-only and is not exposed here.
217
+ *
218
+ * These methods require a user session and throw
219
+ * {@link NotAuthenticatedError} if the user is not authenticated.
220
+ */
221
+ readonly tokenSale: CoinListTokenSaleNamespace;
222
+ /**
223
+ * On-chain swap operations: quoting a swap, reading swap-contract state, and
224
+ * proving/allow-listing wallet ownership — e.g.
232
225
  * `coinlist.swap.getOutputToken({ contractAddress, chain })`.
233
226
  *
234
227
  * These methods require a user session and throw
@@ -4,30 +4,26 @@ import {
4
4
  HttpError,
5
5
  PUBLIC_API_BASE_URL,
6
6
  createKycToken,
7
- createParticipation,
8
7
  fetchOfferDetails,
9
8
  fetchOfferRequirements,
10
9
  fetchOffers,
11
10
  fetchOffersPage,
12
- fetchParticipation,
13
- fetchParticipations,
14
- fetchParticipationsPage,
15
11
  fetchPii,
16
12
  fetchRequirementStatuses,
17
13
  submitDocument
18
- } from "../chunk-MKCOK3DF.js";
14
+ } from "../chunk-TBU3EBNM.js";
19
15
  import {
20
16
  ClientCredentialsOAuth,
21
- OAuthSession
22
- } from "../chunk-AAER5LOL.js";
23
- import {
17
+ Erc20NamespaceImpl,
24
18
  NotAuthenticatedError,
19
+ OAuthSession,
25
20
  SwapNamespaceImpl,
21
+ TokenSaleNamespaceImpl,
26
22
  connectExternalWallet,
27
23
  createWalletOwnershipChallenge,
28
24
  listOptionAddresses,
29
25
  removeOptionAddress
30
- } from "../chunk-Z2HAA2TI.js";
26
+ } from "../chunk-UOHD7US2.js";
31
27
 
32
28
  // src/server/api/api.server.ts
33
29
  var Api = class {
@@ -66,10 +62,13 @@ var CoinListServerImpl = class {
66
62
  // than re-sending with the same expired token and wasting a round-trip.
67
63
  (refresh) => refresh && !this._config.sessionStore.setSession ? Promise.resolve(null) : this.accessToken()
68
64
  );
69
- this.swap = new SwapNamespaceImpl({
65
+ const ctx = {
70
66
  api: this.api,
71
67
  ensureUserAuthenticated: () => this.ensureUserAuthenticated()
72
- });
68
+ };
69
+ this.erc20 = new Erc20NamespaceImpl(ctx);
70
+ this.tokenSale = new TokenSaleNamespaceImpl(ctx);
71
+ this.swap = new SwapNamespaceImpl(ctx);
73
72
  }
74
73
  async completeOAuth(code, codeVerifier) {
75
74
  const sessionStore = this._config.sessionStore;
@@ -190,22 +189,6 @@ var CoinListServerImpl = class {
190
189
  await this.ensureAuthenticated(clientCreds);
191
190
  return fetchOfferDetails(this.api, id, clientCreds);
192
191
  }
193
- async fetchParticipations(offerId) {
194
- await this.ensureUserAuthenticated();
195
- return fetchParticipations(this.api, offerId);
196
- }
197
- async fetchParticipationsPage(params) {
198
- await this.ensureUserAuthenticated();
199
- return fetchParticipationsPage(this.api, params);
200
- }
201
- async fetchParticipation(id) {
202
- await this.ensureUserAuthenticated();
203
- return fetchParticipation(this.api, id);
204
- }
205
- async createParticipation(params) {
206
- await this.ensureUserAuthenticated();
207
- return createParticipation(this.api, params);
208
- }
209
192
  async createWalletOwnershipChallenge(params) {
210
193
  await this.ensureUserAuthenticated();
211
194
  return createWalletOwnershipChallenge(this.api, params);
@@ -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 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":"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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 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 CoinListErc20Namespace,\n Erc20NamespaceImpl,\n} from '@/shared/core/erc20-namespace';\nimport {\n type CoinListSwapNamespace,\n SwapNamespaceImpl,\n} from '@/shared/core/swap-namespace';\nimport {\n type CoinListTokenSaleNamespace,\n TokenSaleNamespaceImpl,\n} from '@/shared/core/token-sale-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 { 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 * 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 * Generic ERC-20 reads (token allowance and balance) — e.g.\n * `coinlist.erc20.getTokenBalance({ ... })`.\n *\n * These methods require a user session and throw\n * {@link NotAuthenticatedError} if the user is not authenticated.\n */\n readonly erc20: CoinListErc20Namespace;\n\n /**\n * Token-sale operations: listing, reading, and recording participations —\n * e.g. `coinlist.tokenSale.fetchParticipations()`. The on-chain\n * `executeTokenSale` flow is client-only and is not exposed here.\n *\n * These methods require a user session and throw\n * {@link NotAuthenticatedError} if the user is not authenticated.\n */\n readonly tokenSale: CoinListTokenSaleNamespace;\n\n /**\n * On-chain swap operations: quoting a swap, reading swap-contract state, and\n * 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 erc20: CoinListErc20Namespace;\n readonly tokenSale: CoinListTokenSaleNamespace;\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 const ctx = {\n api: this.api,\n ensureUserAuthenticated: () => this.ensureUserAuthenticated(),\n };\n this.erc20 = new Erc20NamespaceImpl(ctx);\n this.tokenSale = new TokenSaleNamespaceImpl(ctx);\n this.swap = new SwapNamespaceImpl(ctx);\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 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":"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","names":[]}
@@ -45,6 +45,7 @@ __export(shared_exports, {
45
45
  DEFAULT_SLIPPAGE_BPS: () => DEFAULT_SLIPPAGE_BPS,
46
46
  DocumentSubmission: () => DocumentSubmission,
47
47
  ERC20_ABI: () => ERC20_ABI,
48
+ Erc20NamespaceImpl: () => Erc20NamespaceImpl,
48
49
  EvmContractAddress: () => EvmContractAddress,
49
50
  EvmWalletAddress: () => EvmWalletAddress,
50
51
  FaqItem: () => FaqItem,
@@ -101,6 +102,7 @@ __export(shared_exports, {
101
102
  TermItem: () => TermItem,
102
103
  TokenAllowance: () => TokenAllowance,
103
104
  TokenBalance: () => TokenBalance,
105
+ TokenSaleNamespaceImpl: () => TokenSaleNamespaceImpl,
104
106
  TxExplorerUrl: () => TxExplorerUrl,
105
107
  USDC: () => USDC,
106
108
  USDC_SYMBOL: () => USDC_SYMBOL,
@@ -1047,6 +1049,21 @@ function toErc20Asset(dto) {
1047
1049
  };
1048
1050
  }
1049
1051
 
1052
+ // src/shared/core/erc20-namespace.ts
1053
+ var Erc20NamespaceImpl = class {
1054
+ constructor(ctx) {
1055
+ this.ctx = ctx;
1056
+ }
1057
+ async getTokenAllowance(params) {
1058
+ await this.ctx.ensureUserAuthenticated();
1059
+ return getTokenAllowance(this.ctx.api, params);
1060
+ }
1061
+ async getTokenBalance(params) {
1062
+ await this.ctx.ensureUserAuthenticated();
1063
+ return getTokenBalance(this.ctx.api, params);
1064
+ }
1065
+ };
1066
+
1050
1067
  // src/shared/types/asset.ts
1051
1068
  var AssetId = (value) => value;
1052
1069
  var AssetCode = (value) => value;
@@ -1059,6 +1076,22 @@ var Asset = {
1059
1076
  })
1060
1077
  };
1061
1078
 
1079
+ // src/shared/types/offer.ts
1080
+ var OfferId = (value) => value;
1081
+ var OfferSlug = (value) => value;
1082
+ var Offer = {
1083
+ fromDto: (dto) => ({
1084
+ id: OfferId(dto.id),
1085
+ slug: OfferSlug(dto.slug),
1086
+ type: dto.type,
1087
+ tagline: dto.tagline,
1088
+ bannerUrl: dto.banner_url,
1089
+ logoUrl: dto.logo_url,
1090
+ startsAt: new Date(dto.starts_at),
1091
+ endsAt: dto.ends_at ? new Date(dto.ends_at) : null
1092
+ })
1093
+ };
1094
+
1062
1095
  // src/shared/utils.ts
1063
1096
  async function sha256(data) {
1064
1097
  const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
@@ -1095,21 +1128,6 @@ function notBlankStringOrNull(value) {
1095
1128
  }
1096
1129
  }
1097
1130
 
1098
- // src/shared/types/offer.ts
1099
- var OfferId = (value) => value;
1100
- var OfferSlug = (value) => value;
1101
- var Offer = {
1102
- fromDto: (dto) => ({
1103
- id: OfferId(dto.id),
1104
- slug: OfferSlug(dto.slug),
1105
- tagline: notBlankStringOrNull(dto.tagline),
1106
- bannerUrl: notBlankStringOrNull(dto.banner_url),
1107
- logoUrl: notBlankStringOrNull(dto.logo_url),
1108
- startsAt: new Date(dto.starts_at),
1109
- endsAt: new Date(dto.ends_at)
1110
- })
1111
- };
1112
-
1113
1131
  // src/shared/types/offer-detail.ts
1114
1132
  var OfferOptionId = (value) => value;
1115
1133
  var OfferOptionSlug = (value) => value;
@@ -1136,16 +1154,17 @@ var OfferDetail = {
1136
1154
  return {
1137
1155
  id: OfferId(dto.id),
1138
1156
  slug: OfferSlug(dto.slug),
1157
+ type: dto.type,
1139
1158
  name: dto.name,
1140
1159
  asset: Asset.fromDto(dto.asset),
1141
1160
  fundingAssets: dto.funding_assets.map(Asset.fromDto),
1142
1161
  about: notBlankStringOrNull(dto.about),
1143
- tagline: notBlankStringOrNull(dto.tagline),
1144
- bannerUrl: notBlankStringOrNull(dto.banner_url),
1145
- logoUrl: notBlankStringOrNull(dto.logo_url),
1146
- category: notBlankStringOrNull(dto.category),
1162
+ tagline: dto.tagline,
1163
+ bannerUrl: dto.banner_url,
1164
+ logoUrl: dto.logo_url,
1165
+ category: dto.category,
1147
1166
  startsAt: new Date(dto.starts_at),
1148
- endsAt: new Date(dto.ends_at),
1167
+ endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
1149
1168
  faqs: dto.faqs.map(FaqItem.fromDto),
1150
1169
  links: dto.links.map(Link.fromDto),
1151
1170
  milestones: dto.milestones.map(Milestone.fromDto),
@@ -1281,14 +1300,6 @@ var SwapNamespaceImpl = class {
1281
1300
  await this.ctx.ensureUserAuthenticated();
1282
1301
  return getSwapStatus(this.ctx.api, params);
1283
1302
  }
1284
- async getTokenAllowance(params) {
1285
- await this.ctx.ensureUserAuthenticated();
1286
- return getTokenAllowance(this.ctx.api, params);
1287
- }
1288
- async getTokenBalance(params) {
1289
- await this.ctx.ensureUserAuthenticated();
1290
- return getTokenBalance(this.ctx.api, params);
1291
- }
1292
1303
  async getOutputToken(params) {
1293
1304
  await this.ctx.ensureUserAuthenticated();
1294
1305
  return getSwapOutputToken(this.ctx.api, params);
@@ -1303,6 +1314,110 @@ var SwapNamespaceImpl = class {
1303
1314
  }
1304
1315
  };
1305
1316
 
1317
+ // src/shared/types/participation.ts
1318
+ var ParticipationId = (value) => value;
1319
+ var Blockchain = (value) => value;
1320
+ var WalletAddress = (value) => value;
1321
+ var ParticipationsPaginationParams = {
1322
+ toQueryParams: (params) => {
1323
+ const queryParams = PaginationParams.toQueryParams(params);
1324
+ if (params.offerId) {
1325
+ queryParams["filters[0][field]"] = "offer_id";
1326
+ queryParams["filters[0][op]"] = "==";
1327
+ queryParams["filters[0][value]"] = params.offerId;
1328
+ }
1329
+ return queryParams;
1330
+ }
1331
+ };
1332
+ var Participation = {
1333
+ /** Maps API DTO shape into the SDK participation domain model. */
1334
+ fromDto: (dto) => {
1335
+ const walletAddress = notBlankStringOrNull(dto.wallet_address);
1336
+ return {
1337
+ id: ParticipationId(dto.id),
1338
+ offerId: OfferId(dto.offer_id),
1339
+ offerOptionId: OfferOptionId(dto.offer_option_id),
1340
+ status: dto.status,
1341
+ amount: dto.amount,
1342
+ displayAmount: dto.amount_string,
1343
+ asset: Asset.fromDto(dto.asset),
1344
+ chain: Blockchain(dto.chain),
1345
+ insertedAt: dto.inserted_at ? new Date(dto.inserted_at) : null,
1346
+ updatedAt: dto.updated_at ? new Date(dto.updated_at) : null,
1347
+ walletAddress: walletAddress ? WalletAddress(walletAddress) : null
1348
+ };
1349
+ }
1350
+ };
1351
+ var CreateParticipationParams = {
1352
+ /** Maps participation creation params into API DTO payload. */
1353
+ toDto: (params) => ({
1354
+ offer_id: params.offerId,
1355
+ offer_option_id: params.offerOptionId,
1356
+ chain: params.chain,
1357
+ wallet_address: params.walletAddress,
1358
+ amount: params.amount,
1359
+ asset_id: params.assetId,
1360
+ approval_transaction_hash: params.approvalTransactionHash
1361
+ })
1362
+ };
1363
+
1364
+ // src/shared/api/frontline/participations.ts
1365
+ async function fetchParticipations(api, offerId) {
1366
+ return fetchAllPages(
1367
+ (params) => fetchParticipationsPage(api, params),
1368
+ { offerId }
1369
+ );
1370
+ }
1371
+ async function fetchParticipationsPage(api, params) {
1372
+ const pageDto = await api.send({
1373
+ method: "GET",
1374
+ url: "/v1/participations",
1375
+ queryParams: ParticipationsPaginationParams.toQueryParams(params),
1376
+ attributes: Attributes.protected()
1377
+ });
1378
+ return PaginatedResponse.fromDto(pageDto, Participation.fromDto);
1379
+ }
1380
+ async function fetchParticipation(api, id) {
1381
+ const dto = await api.send({
1382
+ method: "GET",
1383
+ url: `/v1/participations/${id}`,
1384
+ attributes: Attributes.protected()
1385
+ });
1386
+ return Participation.fromDto(dto);
1387
+ }
1388
+ async function createParticipation(api, params) {
1389
+ const dto = await api.send({
1390
+ method: "POST",
1391
+ url: "/v1/participations",
1392
+ body: CreateParticipationParams.toDto(params),
1393
+ attributes: Attributes.protected()
1394
+ });
1395
+ return Participation.fromDto(dto);
1396
+ }
1397
+
1398
+ // src/shared/core/token-sale-namespace.ts
1399
+ var TokenSaleNamespaceImpl = class {
1400
+ constructor(ctx) {
1401
+ this.ctx = ctx;
1402
+ }
1403
+ async fetchParticipations(offerId) {
1404
+ await this.ctx.ensureUserAuthenticated();
1405
+ return fetchParticipations(this.ctx.api, offerId);
1406
+ }
1407
+ async fetchParticipationsPage(params) {
1408
+ await this.ctx.ensureUserAuthenticated();
1409
+ return fetchParticipationsPage(this.ctx.api, params);
1410
+ }
1411
+ async fetchParticipation(id) {
1412
+ await this.ctx.ensureUserAuthenticated();
1413
+ return fetchParticipation(this.ctx.api, id);
1414
+ }
1415
+ async createParticipation(params) {
1416
+ await this.ctx.ensureUserAuthenticated();
1417
+ return createParticipation(this.ctx.api, params);
1418
+ }
1419
+ };
1420
+
1306
1421
  // src/shared/types/oauth.ts
1307
1422
  var AuthorizationCode = (value) => value;
1308
1423
  var CodeVerifier = (value) => value;
@@ -1374,53 +1489,6 @@ var OAuthSession = {
1374
1489
  }
1375
1490
  };
1376
1491
 
1377
- // src/shared/types/participation.ts
1378
- var ParticipationId = (value) => value;
1379
- var Blockchain = (value) => value;
1380
- var WalletAddress = (value) => value;
1381
- var ParticipationsPaginationParams = {
1382
- toQueryParams: (params) => {
1383
- const queryParams = PaginationParams.toQueryParams(params);
1384
- if (params.offerId) {
1385
- queryParams["filters[0][field]"] = "offer_id";
1386
- queryParams["filters[0][op]"] = "==";
1387
- queryParams["filters[0][value]"] = params.offerId;
1388
- }
1389
- return queryParams;
1390
- }
1391
- };
1392
- var Participation = {
1393
- /** Maps API DTO shape into the SDK participation domain model. */
1394
- fromDto: (dto) => {
1395
- const walletAddress = notBlankStringOrNull(dto.wallet_address);
1396
- return {
1397
- id: ParticipationId(dto.id),
1398
- offerId: OfferId(dto.offer_id),
1399
- offerOptionId: OfferOptionId(dto.offer_option_id),
1400
- status: dto.status,
1401
- amount: dto.amount,
1402
- displayAmount: dto.amount_string,
1403
- asset: Asset.fromDto(dto.asset),
1404
- chain: Blockchain(dto.chain),
1405
- insertedAt: dto.inserted_at ? new Date(dto.inserted_at) : null,
1406
- updatedAt: dto.updated_at ? new Date(dto.updated_at) : null,
1407
- walletAddress: walletAddress ? WalletAddress(walletAddress) : null
1408
- };
1409
- }
1410
- };
1411
- var CreateParticipationParams = {
1412
- /** Maps participation creation params into API DTO payload. */
1413
- toDto: (params) => ({
1414
- offer_id: params.offerId,
1415
- offer_option_id: params.offerOptionId,
1416
- chain: params.chain,
1417
- wallet_address: params.walletAddress,
1418
- amount: params.amount,
1419
- asset_id: params.assetId,
1420
- approval_transaction_hash: params.approvalTransactionHash
1421
- })
1422
- };
1423
-
1424
1492
  // src/shared/types/pii.ts
1425
1493
  var Iso2CountryCode = (value) => value;
1426
1494
  var PiiJurisdiction = {
@@ -1506,6 +1574,7 @@ var User = {
1506
1574
  DEFAULT_SLIPPAGE_BPS,
1507
1575
  DocumentSubmission,
1508
1576
  ERC20_ABI,
1577
+ Erc20NamespaceImpl,
1509
1578
  EvmContractAddress,
1510
1579
  EvmWalletAddress,
1511
1580
  FaqItem,
@@ -1562,6 +1631,7 @@ var User = {
1562
1631
  TermItem,
1563
1632
  TokenAllowance,
1564
1633
  TokenBalance,
1634
+ TokenSaleNamespaceImpl,
1565
1635
  TxExplorerUrl,
1566
1636
  USDC,
1567
1637
  USDC_SYMBOL,