@coinlist-co/react 0.12.2-rc.726778a → 0.12.2-rc.9fb6364
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-IRV5YU42.js → chunk-BNMF2HMW.js} +98 -2
- package/dist/chunk-BNMF2HMW.js.map +1 -0
- package/dist/{chunk-3UQPCAU4.js → chunk-KRA6EM2L.js} +2 -2
- package/dist/{chunk-C6F5FOFP.js → chunk-STAHYDLY.js} +52 -19
- package/dist/chunk-STAHYDLY.js.map +1 -0
- package/dist/client/index.cjs +287 -53
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +26 -8
- package/dist/client/index.d.ts +26 -8
- package/dist/client/index.js +182 -39
- package/dist/client/index.js.map +1 -1
- package/dist/server/index.cjs +435 -76
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +47 -38
- package/dist/server/index.d.ts +47 -38
- package/dist/server/index.js +316 -61
- package/dist/server/index.js.map +1 -1
- package/dist/time-B5YOQxuh.d.ts +50 -0
- package/dist/time-BY3apBpc.d.cts +50 -0
- package/dist/{token-registry-snapshot-BNBNuDu1.d.ts → token-registry-snapshot-C1NxdBmF.d.ts} +1 -1
- package/dist/{token-registry-snapshot-CqI6dXM_.d.cts → token-registry-snapshot-DyjrA32p.d.cts} +1 -1
- package/dist/{tokens-namespace-CIWBtgt2.d.cts → tokens-namespace-BJfFeowE.d.cts} +53 -1
- package/dist/{tokens-namespace-CIWBtgt2.d.ts → tokens-namespace-BJfFeowE.d.ts} +53 -1
- package/dist/universal/index.cjs +83 -1
- package/dist/universal/index.cjs.map +1 -1
- package/dist/universal/index.d.cts +5 -4
- package/dist/universal/index.d.ts +5 -4
- package/dist/universal/index.js +10 -2
- package/package.json +1 -1
- package/dist/chunk-C6F5FOFP.js.map +0 -1
- package/dist/chunk-IRV5YU42.js.map +0 -1
- /package/dist/{chunk-3UQPCAU4.js.map → chunk-KRA6EM2L.js.map} +0 -0
package/dist/client/index.d.cts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ButtonHTMLAttributes } from 'react';
|
|
3
|
-
import { A as AuthorizationCode, C as CodeVerifier, L as Logger, W as WalletError, E as Erc20Namespace, a as EthereumChain, b as EvmContractAddress, B as BlockchainAmount, c as CoinListTokenSaleNamespace, O as OfferId, d as OfferOptionId, e as AssetId, P as Participation, f as CoinListTokenSaleNamespaceImpl, U as UniversalNamespaceContext, g as OndoNamespace, h as AssetSymbol, i as OfferSwapContract, j as OndoBuyTransaction, k as OndoSellTransaction, l as OndoSwapTransactionCore, m as OrderBookSide, n as OndoNamespaceImpl, S as SuperstateSwapNamespace, o as WalletsNamespace, p as Bps, q as EvmWalletAddress, r as SuperstateSwapNamespaceImpl, R as RequirementsNamespace, s as Requirement, t as RequirementsNamespaceImpl, u as Config, v as OAuthAccessToken, w as OffersNamespace, T as TokensNamespace, x as StablecoinSymbol, y as Erc20Asset, z as OfferDetail, D as TokenMetadata, F as OfferType, G as OndoSwapOfferDetail, H as CoinListTokenSaleOfferDetail, I as SuperstateSwapOfferDetail, J as Offer, K as RequirementStatusInfo, M as RequirementType, N as RequirementStatusValue, Q as OfferOptionAddress, V as RequirementId, X as KycLevelName, Y as DocumentSubmission, Z as WalletChallengeType, _ as PinoLoggerOptions, $ as OndoTradingStatus, a0 as AssetDecimals, a1 as BuildOndoBuyParams, a2 as BuildOndoSellParams, a3 as OndoQuote, a4 as OndoQuoteSize, a5 as TokenIdentifier, a6 as OfferOptionAddressId, a7 as TokenLogo } from '../tokens-namespace-
|
|
4
|
-
export { a8 as DebugEvent, a9 as FrontlineEventId, aa as HttpError, ab as HttpResponse, ac as KycToken, ad as LogBinding, ae as LogBindings, af as LogCause, ag as LogLevel, ah as LogScope, ai as LogValue, aj as ProductionLogLevel, ak as RedactedWalletError, al as RequestId, am as RpcFailureReason, an as SafeEvent, ao as SafeFields, ap as UnredactedFields } from '../tokens-namespace-
|
|
5
|
-
import { P as PKCEConfig, E as EvmWallet, S as SwapQuote, A as AssetIconUrl, a as ShortenedWalletAddress, F as FormattedAmountAssetUi, b as FormattedPercentUi, T as TxExplorerUrl, C as ConnectWallet, N as NonEmptyArray, c as TokenRegistrySnapshot } from '../token-registry-snapshot-
|
|
6
|
-
export { B as BroadcastTxParams, d as EvmSigner, W as WriteContractParams } from '../token-registry-snapshot-
|
|
3
|
+
import { A as AuthorizationCode, C as CodeVerifier, L as Logger, W as WalletError, E as Erc20Namespace, a as EthereumChain, b as EvmContractAddress, B as BlockchainAmount, c as CoinListTokenSaleNamespace, O as OfferId, d as OfferOptionId, e as AssetId, P as Participation, f as CoinListTokenSaleNamespaceImpl, U as UniversalNamespaceContext, g as OndoNamespace, h as AssetSymbol, i as OfferSwapContract, j as OndoBuyTransaction, k as OndoSellTransaction, l as OndoSwapTransactionCore, m as OrderBookSide, n as OndoNamespaceImpl, S as SuperstateSwapNamespace, o as WalletsNamespace, p as Bps, q as EvmWalletAddress, r as SuperstateSwapNamespaceImpl, R as RequirementsNamespace, s as Requirement, t as RequirementsNamespaceImpl, u as Config, v as OAuthAccessToken, w as OffersNamespace, T as TokensNamespace, x as StablecoinSymbol, y as Erc20Asset, z as OfferDetail, D as TokenMetadata, F as OfferType, G as OndoSwapOfferDetail, H as CoinListTokenSaleOfferDetail, I as SuperstateSwapOfferDetail, J as Offer, K as RequirementStatusInfo, M as RequirementType, N as RequirementStatusValue, Q as OfferOptionAddress, V as RequirementId, X as KycLevelName, Y as DocumentSubmission, Z as WalletChallengeType, _ as PinoLoggerOptions, $ as OndoTradingStatus, a0 as AssetDecimals, a1 as BuildOndoBuyParams, a2 as BuildOndoSellParams, a3 as OndoQuote, a4 as OndoQuoteSize, a5 as TokenIdentifier, a6 as OfferOptionAddressId, a7 as TokenLogo } from '../tokens-namespace-BJfFeowE.cjs';
|
|
4
|
+
export { a8 as DebugEvent, a9 as FrontlineEventId, aa as HttpError, ab as HttpResponse, ac as KycToken, ad as LogBinding, ae as LogBindings, af as LogCause, ag as LogLevel, ah as LogScope, ai as LogValue, aj as ProductionLogLevel, ak as RedactedWalletError, al as RequestId, am as RpcFailureReason, an as SafeEvent, ao as SafeFields, ap as UnredactedFields } from '../tokens-namespace-BJfFeowE.cjs';
|
|
5
|
+
import { P as PKCEConfig, E as EvmWallet, S as SwapQuote, A as AssetIconUrl, a as ShortenedWalletAddress, F as FormattedAmountAssetUi, b as FormattedPercentUi, T as TxExplorerUrl, C as ConnectWallet, N as NonEmptyArray, c as TokenRegistrySnapshot } from '../token-registry-snapshot-DyjrA32p.cjs';
|
|
6
|
+
export { B as BroadcastTxParams, d as EvmSigner, W as WriteContractParams } from '../token-registry-snapshot-DyjrA32p.cjs';
|
|
7
7
|
import { Hash } from 'viem';
|
|
8
8
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
9
9
|
import { VariantProps } from 'class-variance-authority';
|
|
@@ -698,10 +698,24 @@ declare class ClientSupportNamespaceImpl implements ClientSupportNamespace {
|
|
|
698
698
|
|
|
699
699
|
interface ClientConfig extends Config {
|
|
700
700
|
/**
|
|
701
|
-
* The SDK user must provide this function. It
|
|
702
|
-
*
|
|
703
|
-
*
|
|
704
|
-
*
|
|
701
|
+
* The SDK user must provide this function. It fetches a valid
|
|
702
|
+
* {@link OAuthAccessToken} from your backend. If your backend is in
|
|
703
|
+
* TypeScript, serve `CoinListServer#auth.getAccessToken` from it.
|
|
704
|
+
*
|
|
705
|
+
* Two answers, and they must not be confused:
|
|
706
|
+
*
|
|
707
|
+
* - **Resolve `null`** when there is no session - e.g. your endpoint
|
|
708
|
+
* answered 204. After a 401 the SDK asks once more a second later before
|
|
709
|
+
* it believes it, then signs the user out and calls
|
|
710
|
+
* {@link Config.onSessionExpired}.
|
|
711
|
+
* - **Throw** when you could not find out - a 5xx, a network failure. The
|
|
712
|
+
* SDK keeps its current auth state and fails only the request in hand.
|
|
713
|
+
*
|
|
714
|
+
* So a backend that answers "no session" for its own failures turns every
|
|
715
|
+
* outage into a logout. Map those to an error status and throw on it.
|
|
716
|
+
*
|
|
717
|
+
* The SDK calls this at most once at a time: concurrent requests that all
|
|
718
|
+
* need a new token share one call.
|
|
705
719
|
*/
|
|
706
720
|
getAccessToken: () => Promise<OAuthAccessToken | null>;
|
|
707
721
|
/**
|
|
@@ -810,6 +824,10 @@ interface CoinListClient {
|
|
|
810
824
|
* the user's {@link AuthState}. This is called automatically by
|
|
811
825
|
* {@link CoinListProvider}; you typically do not need to call it yourself
|
|
812
826
|
* unless you are using the client outside of the provider.
|
|
827
|
+
*
|
|
828
|
+
* @throws whatever {@link ClientConfig.getAccessToken} throws. The auth
|
|
829
|
+
* state is then left as it was (`'unknown'` on a first call), since a
|
|
830
|
+
* failure to find out is not a logout.
|
|
813
831
|
*/
|
|
814
832
|
init(): Promise<AuthState>;
|
|
815
833
|
}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode, ButtonHTMLAttributes } from 'react';
|
|
3
|
-
import { A as AuthorizationCode, C as CodeVerifier, L as Logger, W as WalletError, E as Erc20Namespace, a as EthereumChain, b as EvmContractAddress, B as BlockchainAmount, c as CoinListTokenSaleNamespace, O as OfferId, d as OfferOptionId, e as AssetId, P as Participation, f as CoinListTokenSaleNamespaceImpl, U as UniversalNamespaceContext, g as OndoNamespace, h as AssetSymbol, i as OfferSwapContract, j as OndoBuyTransaction, k as OndoSellTransaction, l as OndoSwapTransactionCore, m as OrderBookSide, n as OndoNamespaceImpl, S as SuperstateSwapNamespace, o as WalletsNamespace, p as Bps, q as EvmWalletAddress, r as SuperstateSwapNamespaceImpl, R as RequirementsNamespace, s as Requirement, t as RequirementsNamespaceImpl, u as Config, v as OAuthAccessToken, w as OffersNamespace, T as TokensNamespace, x as StablecoinSymbol, y as Erc20Asset, z as OfferDetail, D as TokenMetadata, F as OfferType, G as OndoSwapOfferDetail, H as CoinListTokenSaleOfferDetail, I as SuperstateSwapOfferDetail, J as Offer, K as RequirementStatusInfo, M as RequirementType, N as RequirementStatusValue, Q as OfferOptionAddress, V as RequirementId, X as KycLevelName, Y as DocumentSubmission, Z as WalletChallengeType, _ as PinoLoggerOptions, $ as OndoTradingStatus, a0 as AssetDecimals, a1 as BuildOndoBuyParams, a2 as BuildOndoSellParams, a3 as OndoQuote, a4 as OndoQuoteSize, a5 as TokenIdentifier, a6 as OfferOptionAddressId, a7 as TokenLogo } from '../tokens-namespace-
|
|
4
|
-
export { a8 as DebugEvent, a9 as FrontlineEventId, aa as HttpError, ab as HttpResponse, ac as KycToken, ad as LogBinding, ae as LogBindings, af as LogCause, ag as LogLevel, ah as LogScope, ai as LogValue, aj as ProductionLogLevel, ak as RedactedWalletError, al as RequestId, am as RpcFailureReason, an as SafeEvent, ao as SafeFields, ap as UnredactedFields } from '../tokens-namespace-
|
|
5
|
-
import { P as PKCEConfig, E as EvmWallet, S as SwapQuote, A as AssetIconUrl, a as ShortenedWalletAddress, F as FormattedAmountAssetUi, b as FormattedPercentUi, T as TxExplorerUrl, C as ConnectWallet, N as NonEmptyArray, c as TokenRegistrySnapshot } from '../token-registry-snapshot-
|
|
6
|
-
export { B as BroadcastTxParams, d as EvmSigner, W as WriteContractParams } from '../token-registry-snapshot-
|
|
3
|
+
import { A as AuthorizationCode, C as CodeVerifier, L as Logger, W as WalletError, E as Erc20Namespace, a as EthereumChain, b as EvmContractAddress, B as BlockchainAmount, c as CoinListTokenSaleNamespace, O as OfferId, d as OfferOptionId, e as AssetId, P as Participation, f as CoinListTokenSaleNamespaceImpl, U as UniversalNamespaceContext, g as OndoNamespace, h as AssetSymbol, i as OfferSwapContract, j as OndoBuyTransaction, k as OndoSellTransaction, l as OndoSwapTransactionCore, m as OrderBookSide, n as OndoNamespaceImpl, S as SuperstateSwapNamespace, o as WalletsNamespace, p as Bps, q as EvmWalletAddress, r as SuperstateSwapNamespaceImpl, R as RequirementsNamespace, s as Requirement, t as RequirementsNamespaceImpl, u as Config, v as OAuthAccessToken, w as OffersNamespace, T as TokensNamespace, x as StablecoinSymbol, y as Erc20Asset, z as OfferDetail, D as TokenMetadata, F as OfferType, G as OndoSwapOfferDetail, H as CoinListTokenSaleOfferDetail, I as SuperstateSwapOfferDetail, J as Offer, K as RequirementStatusInfo, M as RequirementType, N as RequirementStatusValue, Q as OfferOptionAddress, V as RequirementId, X as KycLevelName, Y as DocumentSubmission, Z as WalletChallengeType, _ as PinoLoggerOptions, $ as OndoTradingStatus, a0 as AssetDecimals, a1 as BuildOndoBuyParams, a2 as BuildOndoSellParams, a3 as OndoQuote, a4 as OndoQuoteSize, a5 as TokenIdentifier, a6 as OfferOptionAddressId, a7 as TokenLogo } from '../tokens-namespace-BJfFeowE.js';
|
|
4
|
+
export { a8 as DebugEvent, a9 as FrontlineEventId, aa as HttpError, ab as HttpResponse, ac as KycToken, ad as LogBinding, ae as LogBindings, af as LogCause, ag as LogLevel, ah as LogScope, ai as LogValue, aj as ProductionLogLevel, ak as RedactedWalletError, al as RequestId, am as RpcFailureReason, an as SafeEvent, ao as SafeFields, ap as UnredactedFields } from '../tokens-namespace-BJfFeowE.js';
|
|
5
|
+
import { P as PKCEConfig, E as EvmWallet, S as SwapQuote, A as AssetIconUrl, a as ShortenedWalletAddress, F as FormattedAmountAssetUi, b as FormattedPercentUi, T as TxExplorerUrl, C as ConnectWallet, N as NonEmptyArray, c as TokenRegistrySnapshot } from '../token-registry-snapshot-C1NxdBmF.js';
|
|
6
|
+
export { B as BroadcastTxParams, d as EvmSigner, W as WriteContractParams } from '../token-registry-snapshot-C1NxdBmF.js';
|
|
7
7
|
import { Hash } from 'viem';
|
|
8
8
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
9
9
|
import { VariantProps } from 'class-variance-authority';
|
|
@@ -698,10 +698,24 @@ declare class ClientSupportNamespaceImpl implements ClientSupportNamespace {
|
|
|
698
698
|
|
|
699
699
|
interface ClientConfig extends Config {
|
|
700
700
|
/**
|
|
701
|
-
* The SDK user must provide this function. It
|
|
702
|
-
*
|
|
703
|
-
*
|
|
704
|
-
*
|
|
701
|
+
* The SDK user must provide this function. It fetches a valid
|
|
702
|
+
* {@link OAuthAccessToken} from your backend. If your backend is in
|
|
703
|
+
* TypeScript, serve `CoinListServer#auth.getAccessToken` from it.
|
|
704
|
+
*
|
|
705
|
+
* Two answers, and they must not be confused:
|
|
706
|
+
*
|
|
707
|
+
* - **Resolve `null`** when there is no session - e.g. your endpoint
|
|
708
|
+
* answered 204. After a 401 the SDK asks once more a second later before
|
|
709
|
+
* it believes it, then signs the user out and calls
|
|
710
|
+
* {@link Config.onSessionExpired}.
|
|
711
|
+
* - **Throw** when you could not find out - a 5xx, a network failure. The
|
|
712
|
+
* SDK keeps its current auth state and fails only the request in hand.
|
|
713
|
+
*
|
|
714
|
+
* So a backend that answers "no session" for its own failures turns every
|
|
715
|
+
* outage into a logout. Map those to an error status and throw on it.
|
|
716
|
+
*
|
|
717
|
+
* The SDK calls this at most once at a time: concurrent requests that all
|
|
718
|
+
* need a new token share one call.
|
|
705
719
|
*/
|
|
706
720
|
getAccessToken: () => Promise<OAuthAccessToken | null>;
|
|
707
721
|
/**
|
|
@@ -810,6 +824,10 @@ interface CoinListClient {
|
|
|
810
824
|
* the user's {@link AuthState}. This is called automatically by
|
|
811
825
|
* {@link CoinListProvider}; you typically do not need to call it yourself
|
|
812
826
|
* unless you are using the client outside of the provider.
|
|
827
|
+
*
|
|
828
|
+
* @throws whatever {@link ClientConfig.getAccessToken} throws. The auth
|
|
829
|
+
* state is then left as it was (`'unknown'` on a first call), since a
|
|
830
|
+
* failure to find out is not a logout.
|
|
813
831
|
*/
|
|
814
832
|
init(): Promise<AuthState>;
|
|
815
833
|
}
|
package/dist/client/index.js
CHANGED
|
@@ -4,8 +4,10 @@ import {
|
|
|
4
4
|
PINO_LEVEL,
|
|
5
5
|
SDK_LOGGER_NAME,
|
|
6
6
|
loggerOverPino,
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
notifySessionExpired,
|
|
8
|
+
publicClients,
|
|
9
|
+
systemDelay
|
|
10
|
+
} from "../chunk-STAHYDLY.js";
|
|
9
11
|
import {
|
|
10
12
|
AuthorizationCode,
|
|
11
13
|
CodeVerifier,
|
|
@@ -39,7 +41,7 @@ import {
|
|
|
39
41
|
ondoQuoteOfferDeadline,
|
|
40
42
|
superstateSwapContractAddress,
|
|
41
43
|
swapSpender
|
|
42
|
-
} from "../chunk-
|
|
44
|
+
} from "../chunk-KRA6EM2L.js";
|
|
43
45
|
import {
|
|
44
46
|
API_VERSION,
|
|
45
47
|
AssetDecimals,
|
|
@@ -58,6 +60,7 @@ import {
|
|
|
58
60
|
HEADER_USER_AGENT,
|
|
59
61
|
HttpError,
|
|
60
62
|
KycToken,
|
|
63
|
+
Millis,
|
|
61
64
|
NA_AMOUNT_ASSET_UI,
|
|
62
65
|
NotAuthenticatedError,
|
|
63
66
|
OAUTH_PAGE_PATH,
|
|
@@ -67,6 +70,7 @@ import {
|
|
|
67
70
|
RequirementsNamespaceImpl,
|
|
68
71
|
SUPERSTATE_SWAP_ABI,
|
|
69
72
|
SUPPORT_NEW_TICKET_URL,
|
|
73
|
+
SentWith,
|
|
70
74
|
SuperstateSwapNamespaceImpl,
|
|
71
75
|
TokensNamespaceImpl,
|
|
72
76
|
VERIFY_IDENTITY_ACCREDITATION_PATH,
|
|
@@ -85,11 +89,12 @@ import {
|
|
|
85
89
|
getNetworkName,
|
|
86
90
|
getUUIDv4,
|
|
87
91
|
internalLogger,
|
|
92
|
+
isRejectedToken,
|
|
88
93
|
parseBlockchainAmount,
|
|
89
94
|
shortenAddress,
|
|
90
95
|
txExplorerUrl,
|
|
91
96
|
usdAmount
|
|
92
|
-
} from "../chunk-
|
|
97
|
+
} from "../chunk-BNMF2HMW.js";
|
|
93
98
|
|
|
94
99
|
// src/client/CoinListProvider.tsx
|
|
95
100
|
import {
|
|
@@ -149,6 +154,159 @@ var ApiClient = class {
|
|
|
149
154
|
}
|
|
150
155
|
};
|
|
151
156
|
|
|
157
|
+
// src/client/core/auth/client-access-token.ts
|
|
158
|
+
var CONFIRM_DELAY = Millis.of(1e3);
|
|
159
|
+
var Generation = {
|
|
160
|
+
initial: 0,
|
|
161
|
+
next: (generation) => generation + 1
|
|
162
|
+
};
|
|
163
|
+
var ClientAccessToken = class {
|
|
164
|
+
constructor(env) {
|
|
165
|
+
this.env = env;
|
|
166
|
+
this.state = { type: "unknown" };
|
|
167
|
+
this.hostCall = null;
|
|
168
|
+
/**
|
|
169
|
+
* Bumped by {@link clear}. A host call that started before a logout must not
|
|
170
|
+
* log the user back in when it lands, so every write checks it first. A 401
|
|
171
|
+
* that arrives after the logout never starts one: `'logged-out'` refuses it.
|
|
172
|
+
*/
|
|
173
|
+
this.generation = Generation.initial;
|
|
174
|
+
this.log = internalLogger(env.logger, "AUTH").child({
|
|
175
|
+
op: "getAccessToken"
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
authState() {
|
|
179
|
+
return this.state.type;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Asks the host for the current token, whatever is cached.
|
|
183
|
+
*
|
|
184
|
+
* Never answers from a host call already in flight: one started before a
|
|
185
|
+
* login (the mount's `init()`, racing the OAuth callback's) would hand back
|
|
186
|
+
* the answer from before the session cookie existed. It waits for that call
|
|
187
|
+
* to settle instead, so that call's verdict still lands, then asks afresh.
|
|
188
|
+
* A logout while it waits still wins.
|
|
189
|
+
*
|
|
190
|
+
* @throws whatever the host's `getAccessToken` throws.
|
|
191
|
+
*/
|
|
192
|
+
async load() {
|
|
193
|
+
const generation = this.generation;
|
|
194
|
+
if (this.hostCall !== null) {
|
|
195
|
+
await this.hostCall.catch(() => null);
|
|
196
|
+
}
|
|
197
|
+
await this.ask(SentWith.noUserToken, generation);
|
|
198
|
+
return this.authState();
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* The HTTP pipeline's token source: see {@link TokenTrigger}.
|
|
202
|
+
*
|
|
203
|
+
* @throws whatever the host's `getAccessToken` throws.
|
|
204
|
+
*/
|
|
205
|
+
async get(trigger) {
|
|
206
|
+
const decision = decideToken(this.state, trigger);
|
|
207
|
+
switch (decision.type) {
|
|
208
|
+
case "serve":
|
|
209
|
+
return decision.token;
|
|
210
|
+
case "ask":
|
|
211
|
+
return this.ask(decision.rejected, this.generation);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/** Forgets the token: `auth.logout()`. Never an expiry, so never notifies. */
|
|
215
|
+
clear() {
|
|
216
|
+
this.generation = Generation.next(this.generation);
|
|
217
|
+
this.hostCall = null;
|
|
218
|
+
this.state = { type: "logged-out" };
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* A request that carried no user token was not refused for a token, so the
|
|
222
|
+
* host's first answer stands. One that was is confirmed before it is
|
|
223
|
+
* believed.
|
|
224
|
+
*/
|
|
225
|
+
async ask(rejected, generation) {
|
|
226
|
+
if (generation !== this.generation) {
|
|
227
|
+
return currentToken(this.state);
|
|
228
|
+
}
|
|
229
|
+
const first = await this.callHost();
|
|
230
|
+
switch (rejected.type) {
|
|
231
|
+
case "no-user-token":
|
|
232
|
+
return this.commit(first, generation);
|
|
233
|
+
case "user-token":
|
|
234
|
+
return isFresh(first, rejected) ? this.commit(first, generation) : this.confirm(rejected, generation);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
async confirm(rejected, generation) {
|
|
238
|
+
this.log.warn(() => ({
|
|
239
|
+
msg: "host returned no fresh token; asking again before signing out"
|
|
240
|
+
}));
|
|
241
|
+
await this.env.delay(CONFIRM_DELAY);
|
|
242
|
+
const second = await this.callHost();
|
|
243
|
+
return isFresh(second, rejected) ? this.commit(second, generation) : this.expire(generation);
|
|
244
|
+
}
|
|
245
|
+
/** The host's `getAccessToken`, joining a call already in flight. */
|
|
246
|
+
callHost() {
|
|
247
|
+
if (this.hostCall !== null) {
|
|
248
|
+
this.log.debug(() => ({ msg: "joined a host call already in flight" }));
|
|
249
|
+
return this.hostCall;
|
|
250
|
+
}
|
|
251
|
+
const call = (async () => this.env.getAccessToken())().finally(() => {
|
|
252
|
+
if (this.hostCall === call) {
|
|
253
|
+
this.hostCall = null;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
this.hostCall = call;
|
|
257
|
+
return call;
|
|
258
|
+
}
|
|
259
|
+
commit(token, generation) {
|
|
260
|
+
if (generation !== this.generation) {
|
|
261
|
+
return currentToken(this.state);
|
|
262
|
+
}
|
|
263
|
+
this.state = token === null ? { type: "logged-out" } : { type: "logged-in", token };
|
|
264
|
+
return token;
|
|
265
|
+
}
|
|
266
|
+
expire(generation) {
|
|
267
|
+
if (generation !== this.generation) {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
const wasLoggedIn = this.state.type === "logged-in";
|
|
271
|
+
this.state = { type: "logged-out" };
|
|
272
|
+
if (wasLoggedIn) {
|
|
273
|
+
this.log.info(() => ({ msg: "session expired" }));
|
|
274
|
+
notifySessionExpired(this.env.onSessionExpired, this.log);
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
function decideToken(state, trigger) {
|
|
280
|
+
switch (trigger.type) {
|
|
281
|
+
case "before-request":
|
|
282
|
+
return state.type === "unknown" ? { type: "ask", rejected: SentWith.noUserToken } : { type: "serve", token: currentToken(state) };
|
|
283
|
+
case "after-401":
|
|
284
|
+
switch (state.type) {
|
|
285
|
+
// A logout or an expiry verdict: only `load()` may log back in, so a
|
|
286
|
+
// 401 to a request sent before it must not ask the host again.
|
|
287
|
+
case "logged-out":
|
|
288
|
+
return { type: "serve", token: null };
|
|
289
|
+
// Another request may already have renewed since this one was sent.
|
|
290
|
+
case "logged-in":
|
|
291
|
+
return isRejectedToken(state.token, trigger.rejected) ? { type: "ask", rejected: trigger.rejected } : { type: "serve", token: state.token };
|
|
292
|
+
case "unknown":
|
|
293
|
+
return { type: "ask", rejected: trigger.rejected };
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function currentToken(state) {
|
|
298
|
+
switch (state.type) {
|
|
299
|
+
case "logged-in":
|
|
300
|
+
return state.token;
|
|
301
|
+
case "unknown":
|
|
302
|
+
case "logged-out":
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function isFresh(token, rejected) {
|
|
307
|
+
return token !== null && !isRejectedToken(token, rejected);
|
|
308
|
+
}
|
|
309
|
+
|
|
152
310
|
// src/client/core/auth/client-auth-namespace.ts
|
|
153
311
|
var OAUTH_STATE_KEY = "coinlist.oauth_state";
|
|
154
312
|
var OAUTH_CODE_VERIFIER_KEY = "coinlist.oauth_code_verifier";
|
|
@@ -963,35 +1121,38 @@ var ClientSupportNamespaceImpl = class {
|
|
|
963
1121
|
|
|
964
1122
|
// src/client/core/coinlist-client.ts
|
|
965
1123
|
var CoinListClientImpl = class {
|
|
966
|
-
constructor(
|
|
967
|
-
this.
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
1124
|
+
constructor(config) {
|
|
1125
|
+
this.config = config;
|
|
1126
|
+
const logger = config.logger ?? null;
|
|
1127
|
+
const accessToken = new ClientAccessToken({
|
|
1128
|
+
getAccessToken: () => config.getAccessToken(),
|
|
1129
|
+
onSessionExpired: config.onSessionExpired,
|
|
1130
|
+
logger,
|
|
1131
|
+
...systemDelay
|
|
1132
|
+
});
|
|
1133
|
+
this.accessToken = accessToken;
|
|
971
1134
|
this.api = new ApiClient(
|
|
972
1135
|
{
|
|
973
|
-
baseUrl:
|
|
1136
|
+
baseUrl: config.baseUrl || PUBLIC_API_BASE_URL,
|
|
974
1137
|
xApiVersion: API_VERSION
|
|
975
1138
|
},
|
|
976
|
-
|
|
1139
|
+
(trigger) => accessToken.get(trigger),
|
|
977
1140
|
logger
|
|
978
1141
|
);
|
|
979
1142
|
const ctx = {
|
|
980
1143
|
api: this.api,
|
|
981
|
-
rpc: publicClients(this.api,
|
|
1144
|
+
rpc: publicClients(this.api, config.rpc, config.logger ?? null),
|
|
982
1145
|
logger,
|
|
983
1146
|
ensureUserAuthenticated: async () => this.ensureAuthenticated()
|
|
984
1147
|
};
|
|
985
|
-
this.auth = new ClientAuthNamespaceImpl(
|
|
986
|
-
getState: () =>
|
|
987
|
-
clearAccessToken: () =>
|
|
988
|
-
this._accessToken = null;
|
|
989
|
-
}
|
|
1148
|
+
this.auth = new ClientAuthNamespaceImpl(config, {
|
|
1149
|
+
getState: () => accessToken.authState(),
|
|
1150
|
+
clearAccessToken: () => accessToken.clear()
|
|
990
1151
|
});
|
|
991
1152
|
this.offers = new OffersNamespaceImpl(ctx);
|
|
992
1153
|
this.requirements = new ClientRequirementsNamespaceImpl(
|
|
993
1154
|
ctx,
|
|
994
|
-
|
|
1155
|
+
config.coinlistBaseUrl
|
|
995
1156
|
);
|
|
996
1157
|
this.wallets = new WalletsNamespaceImpl(ctx);
|
|
997
1158
|
this.erc20 = new Erc20NamespaceImpl(ctx);
|
|
@@ -1003,34 +1164,16 @@ var CoinListClientImpl = class {
|
|
|
1003
1164
|
);
|
|
1004
1165
|
this.ondo = new ClientOndoNamespaceImpl(ctx, this.erc20);
|
|
1005
1166
|
this.tokens = new TokensNamespaceImpl(
|
|
1006
|
-
|
|
1167
|
+
config.tokensBaseUrl ?? NABU_BASE_URL,
|
|
1007
1168
|
logger
|
|
1008
1169
|
);
|
|
1009
1170
|
this.support = new ClientSupportNamespaceImpl(logger);
|
|
1010
1171
|
}
|
|
1011
1172
|
async init() {
|
|
1012
|
-
|
|
1013
|
-
return this.getAuthState();
|
|
1014
|
-
}
|
|
1015
|
-
async fetchAccessToken(refresh) {
|
|
1016
|
-
if (!refresh && this._accessToken !== void 0) return this._accessToken;
|
|
1017
|
-
try {
|
|
1018
|
-
const accessToken = await this._config.getAccessToken();
|
|
1019
|
-
this._accessToken = accessToken;
|
|
1020
|
-
return accessToken;
|
|
1021
|
-
} catch (_) {
|
|
1022
|
-
this._accessToken = null;
|
|
1023
|
-
return null;
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
getAuthState() {
|
|
1027
|
-
if (this._accessToken === void 0) {
|
|
1028
|
-
return "unknown";
|
|
1029
|
-
}
|
|
1030
|
-
return this._accessToken !== null ? "logged-in" : "logged-out";
|
|
1173
|
+
return this.accessToken.load();
|
|
1031
1174
|
}
|
|
1032
1175
|
ensureAuthenticated() {
|
|
1033
|
-
if (this.
|
|
1176
|
+
if (this.accessToken.authState() !== "logged-in") {
|
|
1034
1177
|
throw new NotAuthenticatedError();
|
|
1035
1178
|
}
|
|
1036
1179
|
}
|