@coinlist-co/react 0.10.1 → 0.11.1-rc.209af8d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -0
- package/dist/chunk-3Z4PLLV7.js +2249 -0
- package/dist/chunk-3Z4PLLV7.js.map +1 -0
- package/dist/{chunk-AQVCOWOV.js → chunk-T4ANQVQA.js} +216 -317
- package/dist/chunk-T4ANQVQA.js.map +1 -0
- package/dist/chunk-YPFS2SAD.js +279 -0
- package/dist/chunk-YPFS2SAD.js.map +1 -0
- package/dist/client/index.cjs +11325 -3316
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +4243 -881
- package/dist/client/index.d.ts +4243 -881
- package/dist/client/index.js +9103 -2389
- package/dist/client/index.js.map +1 -1
- package/dist/collections-B0nu_6q5.d.ts +116 -0
- package/dist/collections-DdLA4_GN.d.cts +116 -0
- package/dist/config-D0r6GyPL.d.cts +2638 -0
- package/dist/config-D0r6GyPL.d.ts +2638 -0
- package/dist/server/index.cjs +1631 -514
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +266 -162
- package/dist/server/index.d.ts +266 -162
- package/dist/server/index.js +235 -169
- package/dist/server/index.js.map +1 -1
- package/dist/shared/index.cjs +2235 -926
- package/dist/shared/index.cjs.map +1 -1
- package/dist/shared/index.d.cts +256 -132
- package/dist/shared/index.d.ts +256 -132
- package/dist/shared/index.js +102 -28
- package/package.json +12 -8
- package/dist/chunk-AQVCOWOV.js.map +0 -1
- package/dist/chunk-TBU3EBNM.js +0 -442
- package/dist/chunk-TBU3EBNM.js.map +0 -1
- package/dist/chunk-UOHD7US2.js +0 -855
- package/dist/chunk-UOHD7US2.js.map +0 -1
- package/dist/collections-Bv1Oxzu_.d.ts +0 -28
- package/dist/collections-DDyxbOPZ.d.cts +0 -28
- package/dist/requirement-oVZA1INj.d.cts +0 -1040
- package/dist/requirement-oVZA1INj.d.ts +0 -1040
package/dist/shared/index.cjs
CHANGED
|
@@ -32,20 +32,26 @@ __export(shared_exports, {
|
|
|
32
32
|
Blockchain: () => Blockchain,
|
|
33
33
|
BlockchainAmount: () => BlockchainAmount,
|
|
34
34
|
Bps: () => Bps,
|
|
35
|
+
Chain: () => Chain,
|
|
35
36
|
ClientCredentialsOAuth: () => ClientCredentialsOAuth,
|
|
36
37
|
ClientId: () => ClientId,
|
|
37
38
|
ClientSecret: () => ClientSecret,
|
|
38
39
|
CodeChallenge: () => CodeChallenge,
|
|
39
40
|
CodeVerifier: () => CodeVerifier,
|
|
41
|
+
CoinListTokenSaleNamespaceImpl: () => CoinListTokenSaleNamespaceImpl,
|
|
40
42
|
ConnectExternalWalletParams: () => ConnectExternalWalletParams,
|
|
41
43
|
CreateParticipationParams: () => CreateParticipationParams,
|
|
42
44
|
CreateWalletOwnershipChallengeParams: () => CreateWalletOwnershipChallengeParams,
|
|
43
45
|
Cursor: () => Cursor,
|
|
44
46
|
DEFAULT_AMOUNT_TO_COMPUTE_PRICE: () => DEFAULT_AMOUNT_TO_COMPUTE_PRICE,
|
|
47
|
+
DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE: () => DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE,
|
|
45
48
|
DEFAULT_SLIPPAGE_BPS: () => DEFAULT_SLIPPAGE_BPS,
|
|
49
|
+
DecimalString: () => DecimalString,
|
|
46
50
|
DocumentSubmission: () => DocumentSubmission,
|
|
47
51
|
ERC20_ABI: () => ERC20_ABI,
|
|
52
|
+
ETHEREUM_CHAINS: () => ETHEREUM_CHAINS,
|
|
48
53
|
Erc20NamespaceImpl: () => Erc20NamespaceImpl,
|
|
54
|
+
EthereumChain: () => EthereumChain,
|
|
49
55
|
EvmContractAddress: () => EvmContractAddress,
|
|
50
56
|
EvmWalletAddress: () => EvmWalletAddress,
|
|
51
57
|
FaqItem: () => FaqItem,
|
|
@@ -53,10 +59,13 @@ __export(shared_exports, {
|
|
|
53
59
|
FormattedAmountUi: () => FormattedAmountUi,
|
|
54
60
|
FormattedPercentUi: () => FormattedPercentUi,
|
|
55
61
|
HexEncodedTransactionData: () => HexEncodedTransactionData,
|
|
62
|
+
HttpError: () => HttpError,
|
|
63
|
+
InvariantError: () => InvariantError,
|
|
56
64
|
Iso2CountryCode: () => Iso2CountryCode,
|
|
57
65
|
KnownAssetSymbol: () => KnownAssetSymbol,
|
|
58
66
|
KycToken: () => KycToken,
|
|
59
67
|
Link: () => Link,
|
|
68
|
+
MAX_ASSET_DECIMALS: () => MAX_ASSET_DECIMALS,
|
|
60
69
|
MAX_UINT_256: () => MAX_UINT_256,
|
|
61
70
|
Milestone: () => Milestone,
|
|
62
71
|
NA_AMOUNT_ASSET_UI: () => NA_AMOUNT_ASSET_UI,
|
|
@@ -64,6 +73,9 @@ __export(shared_exports, {
|
|
|
64
73
|
NotImplementedError: () => NotImplementedError,
|
|
65
74
|
OAuthRefreshToken: () => OAuthRefreshToken,
|
|
66
75
|
OAuthSession: () => OAuthSession,
|
|
76
|
+
ONDO_POLL_INTERVAL_MS: () => ONDO_POLL_INTERVAL_MS,
|
|
77
|
+
ONDO_QUOTE_EXPIRY_THRESHOLD_MS: () => ONDO_QUOTE_EXPIRY_THRESHOLD_MS,
|
|
78
|
+
ONDO_SUPPORTED_INPUT_ASSETS: () => ONDO_SUPPORTED_INPUT_ASSETS,
|
|
67
79
|
Offer: () => Offer,
|
|
68
80
|
OfferDetail: () => OfferDetail,
|
|
69
81
|
OfferId: () => OfferId,
|
|
@@ -73,6 +85,12 @@ __export(shared_exports, {
|
|
|
73
85
|
OfferOptionId: () => OfferOptionId,
|
|
74
86
|
OfferOptionSlug: () => OfferOptionSlug,
|
|
75
87
|
OfferSlug: () => OfferSlug,
|
|
88
|
+
OfferToken: () => OfferToken,
|
|
89
|
+
OffersNamespaceImpl: () => OffersNamespaceImpl,
|
|
90
|
+
OndoNamespaceImpl: () => OndoNamespaceImpl,
|
|
91
|
+
OndoQuote: () => OndoQuote,
|
|
92
|
+
OndoSwapTransaction: () => OndoSwapTransaction,
|
|
93
|
+
OndoTradingStatus: () => OndoTradingStatus,
|
|
76
94
|
PKCEState: () => PKCEState,
|
|
77
95
|
PaginatedResponse: () => PaginatedResponse,
|
|
78
96
|
PaginationParams: () => PaginationParams,
|
|
@@ -82,27 +100,37 @@ __export(shared_exports, {
|
|
|
82
100
|
Pii: () => Pii,
|
|
83
101
|
PiiAddress: () => PiiAddress,
|
|
84
102
|
PiiJurisdiction: () => PiiJurisdiction,
|
|
103
|
+
RedactedWalletError: () => RedactedWalletError,
|
|
85
104
|
RedirectUri: () => RedirectUri,
|
|
86
105
|
Requirement: () => Requirement,
|
|
87
106
|
RequirementId: () => RequirementId,
|
|
88
107
|
RequirementStatusInfo: () => RequirementStatusInfo,
|
|
108
|
+
RequirementsNamespaceImpl: () => RequirementsNamespaceImpl,
|
|
89
109
|
SLIPPAGE_OPTIONS_BPS: () => SLIPPAGE_OPTIONS_BPS,
|
|
110
|
+
SOLANA_CHAINS: () => SOLANA_CHAINS,
|
|
111
|
+
STABLE_DECIMALS: () => STABLE_DECIMALS,
|
|
112
|
+
SUPERSTATE_ISSUER_NAME: () => SUPERSTATE_ISSUER_NAME,
|
|
113
|
+
SUPERSTATE_SUPPORTED_INPUT_ASSETS: () => SUPERSTATE_SUPPORTED_INPUT_ASSETS,
|
|
90
114
|
SUPERSTATE_SWAP_ABI: () => SUPERSTATE_SWAP_ABI,
|
|
91
115
|
SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA: () => SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA,
|
|
92
|
-
SUPERSTATE_TOS_URL: () => SUPERSTATE_TOS_URL,
|
|
93
116
|
SWAP_POLL_INTERVAL_MS: () => SWAP_POLL_INTERVAL_MS,
|
|
94
117
|
ShortenedWalletAddress: () => ShortenedWalletAddress,
|
|
118
|
+
SolanaChain: () => SolanaChain,
|
|
95
119
|
StablecoinSymbol: () => StablecoinSymbol,
|
|
120
|
+
SuperstateSwapNamespaceImpl: () => SuperstateSwapNamespaceImpl,
|
|
96
121
|
SwapAuthorization: () => SwapAuthorization,
|
|
97
|
-
SwapNamespaceImpl: () => SwapNamespaceImpl,
|
|
98
122
|
SwapPreview: () => SwapPreview,
|
|
99
123
|
SwapQuote: () => SwapQuote,
|
|
100
124
|
SwapStatus: () => SwapStatus,
|
|
101
125
|
TOKEN_REGISTRY: () => TOKEN_REGISTRY,
|
|
102
126
|
TermItem: () => TermItem,
|
|
127
|
+
Ticker: () => Ticker,
|
|
103
128
|
TokenAllowance: () => TokenAllowance,
|
|
104
129
|
TokenBalance: () => TokenBalance,
|
|
105
|
-
|
|
130
|
+
TokenLogo: () => TokenLogo,
|
|
131
|
+
TokenLogoUrl: () => TokenLogoUrl,
|
|
132
|
+
TokenMetadata: () => TokenMetadata,
|
|
133
|
+
TokensNamespaceImpl: () => TokensNamespaceImpl,
|
|
106
134
|
TxExplorerUrl: () => TxExplorerUrl,
|
|
107
135
|
USDC: () => USDC,
|
|
108
136
|
USDC_SYMBOL: () => USDC_SYMBOL,
|
|
@@ -111,11 +139,17 @@ __export(shared_exports, {
|
|
|
111
139
|
User: () => User,
|
|
112
140
|
UserEmail: () => UserEmail,
|
|
113
141
|
UserId: () => UserId,
|
|
142
|
+
ValidationError: () => ValidationError,
|
|
114
143
|
WalletAddress: () => WalletAddress,
|
|
115
144
|
WalletOwnershipChallenge: () => WalletOwnershipChallenge,
|
|
145
|
+
WalletsNamespaceImpl: () => WalletsNamespaceImpl,
|
|
146
|
+
apiErrorCode: () => apiErrorCode,
|
|
116
147
|
applyBps: () => applyBps,
|
|
117
148
|
assertUint256: () => assertUint256,
|
|
118
149
|
assetAmount: () => assetAmount,
|
|
150
|
+
blockchainAmountFromRawOrThrow: () => blockchainAmountFromRawOrThrow,
|
|
151
|
+
chainFromId: () => chainFromId,
|
|
152
|
+
computeOndoPrice: () => computeOndoPrice,
|
|
119
153
|
computePrice: () => computePrice,
|
|
120
154
|
computeSlip: () => computeSlip,
|
|
121
155
|
decodeSwappedOutputAmount: () => decodeSwappedOutputAmount,
|
|
@@ -130,15 +164,182 @@ __export(shared_exports, {
|
|
|
130
164
|
getChainId: () => getChainId,
|
|
131
165
|
getNetworkName: () => getNetworkName,
|
|
132
166
|
isStopped: () => isStopped,
|
|
167
|
+
ondoSwapContractAddress: () => ondoSwapContractAddress,
|
|
133
168
|
parseBlockchainAmount: () => parseBlockchainAmount,
|
|
169
|
+
parseUint256: () => parseUint256,
|
|
134
170
|
shortenAddress: () => shortenAddress,
|
|
171
|
+
superstateSwapContractAddress: () => superstateSwapContractAddress,
|
|
135
172
|
txExplorerUrl: () => txExplorerUrl,
|
|
136
173
|
usdAmount: () => usdAmount
|
|
137
174
|
});
|
|
138
175
|
module.exports = __toCommonJS(shared_exports);
|
|
139
176
|
|
|
177
|
+
// src/shared/api/http-attributes.ts
|
|
178
|
+
var empty = {};
|
|
179
|
+
var concat = (left, right) => ({
|
|
180
|
+
...left,
|
|
181
|
+
...right
|
|
182
|
+
});
|
|
183
|
+
var concatAll = (...items) => {
|
|
184
|
+
let result = empty;
|
|
185
|
+
for (const item of items) {
|
|
186
|
+
result = concat(result, item);
|
|
187
|
+
}
|
|
188
|
+
return result;
|
|
189
|
+
};
|
|
190
|
+
var protectedRequest = () => ({ protected: true });
|
|
191
|
+
var userAgent = () => ({ userAgent: true });
|
|
192
|
+
var idempotencyKey = () => ({
|
|
193
|
+
idempotencyKey: true
|
|
194
|
+
});
|
|
195
|
+
var clientCredentials = (credentials) => ({
|
|
196
|
+
clientCredentials: credentials
|
|
197
|
+
});
|
|
198
|
+
var retryAttempt = (attempt) => ({
|
|
199
|
+
retryAttempt: attempt
|
|
200
|
+
});
|
|
201
|
+
var renewAttempted = (value) => ({
|
|
202
|
+
renewAttempted: value
|
|
203
|
+
});
|
|
204
|
+
var requestId = (id) => ({ requestId: id });
|
|
205
|
+
var getRequestId = (attrs) => attrs?.requestId ?? null;
|
|
206
|
+
var isProtected = (attrs) => attrs?.protected === true;
|
|
207
|
+
var needUserAgent = (attrs) => attrs?.userAgent === true;
|
|
208
|
+
var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
|
|
209
|
+
var getRetryAttempt = (attrs) => attrs?.retryAttempt ?? 0;
|
|
210
|
+
var wasRenewAttempted = (attrs) => attrs?.renewAttempted === true;
|
|
211
|
+
var getClientCredentials = (attrs) => attrs?.clientCredentials;
|
|
212
|
+
var Attributes = {
|
|
213
|
+
empty,
|
|
214
|
+
concat,
|
|
215
|
+
concatAll,
|
|
216
|
+
protected: protectedRequest,
|
|
217
|
+
isProtected,
|
|
218
|
+
userAgent,
|
|
219
|
+
needUserAgent,
|
|
220
|
+
idempotencyKey,
|
|
221
|
+
isIdempotent,
|
|
222
|
+
retryAttempt,
|
|
223
|
+
getRetryAttempt,
|
|
224
|
+
renewAttempted,
|
|
225
|
+
wasRenewAttempted,
|
|
226
|
+
clientCredentials,
|
|
227
|
+
getClientCredentials,
|
|
228
|
+
requestId,
|
|
229
|
+
getRequestId
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// src/shared/api/http.ts
|
|
233
|
+
var HttpError = class extends Error {
|
|
234
|
+
constructor(response) {
|
|
235
|
+
super(`Request failed with ${response.status} status`);
|
|
236
|
+
this.name = "HttpError";
|
|
237
|
+
this.response = response;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Correlates this failure with the `[HTTP]` log lines for the same request,
|
|
241
|
+
* which carry the method, the URL, the duration and every retry. `null` when
|
|
242
|
+
* the response did not come from an {@link HttpClient}.
|
|
243
|
+
*
|
|
244
|
+
* Worth quoting in a bug report: it is what makes a log excerpt readable.
|
|
245
|
+
*/
|
|
246
|
+
get requestId() {
|
|
247
|
+
return this.response.requestId ?? null;
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
function apiErrorCode(error) {
|
|
251
|
+
if (!(error instanceof HttpError)) return null;
|
|
252
|
+
const body = error.response.body;
|
|
253
|
+
if (typeof body !== "object" || body === null) return null;
|
|
254
|
+
const code = body.code;
|
|
255
|
+
return typeof code === "string" ? code : null;
|
|
256
|
+
}
|
|
257
|
+
async function makeRequest(request) {
|
|
258
|
+
const headers = {
|
|
259
|
+
Accept: "application/json",
|
|
260
|
+
...request.method === "POST" && request.body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
261
|
+
...request.headers ?? {}
|
|
262
|
+
};
|
|
263
|
+
const init = {
|
|
264
|
+
method: request.method,
|
|
265
|
+
headers,
|
|
266
|
+
...request.redirect !== void 0 ? { redirect: request.redirect } : {}
|
|
267
|
+
};
|
|
268
|
+
if (request.method === "POST" && request.body !== void 0) {
|
|
269
|
+
init.body = JSON.stringify(request.body);
|
|
270
|
+
}
|
|
271
|
+
const response = await fetch(
|
|
272
|
+
buildUrlWithQueryParams(request.url, request.queryParams),
|
|
273
|
+
init
|
|
274
|
+
);
|
|
275
|
+
const responseHeaders = headersToRecord(response.headers);
|
|
276
|
+
if (response.status === 204 || response.status === 205) {
|
|
277
|
+
return {
|
|
278
|
+
status: response.status,
|
|
279
|
+
body: null,
|
|
280
|
+
headers: responseHeaders
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
if (response.status >= 300 && response.status < 400) {
|
|
284
|
+
await response.text();
|
|
285
|
+
return {
|
|
286
|
+
status: response.status,
|
|
287
|
+
body: null,
|
|
288
|
+
headers: responseHeaders
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
const text = await response.text();
|
|
292
|
+
let body;
|
|
293
|
+
try {
|
|
294
|
+
body = text ? JSON.parse(text) : null;
|
|
295
|
+
} catch (_) {
|
|
296
|
+
throw new HttpError({
|
|
297
|
+
status: response.status,
|
|
298
|
+
headers: responseHeaders,
|
|
299
|
+
body: text
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
status: response.status,
|
|
304
|
+
body,
|
|
305
|
+
headers: responseHeaders
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
function buildUrlWithQueryParams(url, queryParams) {
|
|
309
|
+
if (!queryParams) {
|
|
310
|
+
return url;
|
|
311
|
+
}
|
|
312
|
+
const searchParams = new URLSearchParams();
|
|
313
|
+
for (const [key, value] of Object.entries(queryParams)) {
|
|
314
|
+
if (value === void 0 || value === null) {
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (Array.isArray(value)) {
|
|
318
|
+
for (const item of value) {
|
|
319
|
+
if (item === void 0 || item === null) {
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
searchParams.append(key, String(item));
|
|
323
|
+
}
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
searchParams.append(key, String(value));
|
|
327
|
+
}
|
|
328
|
+
const queryString = searchParams.toString();
|
|
329
|
+
if (!queryString) {
|
|
330
|
+
return url;
|
|
331
|
+
}
|
|
332
|
+
return url.includes("?") ? `${url}&${queryString}` : `${url}?${queryString}`;
|
|
333
|
+
}
|
|
334
|
+
function headersToRecord(headers) {
|
|
335
|
+
const record = {};
|
|
336
|
+
headers.forEach((value, key) => {
|
|
337
|
+
record[key.toLowerCase()] = value;
|
|
338
|
+
});
|
|
339
|
+
return record;
|
|
340
|
+
}
|
|
341
|
+
|
|
140
342
|
// src/shared/api/pagination.ts
|
|
141
|
-
var Cursor = (value) => value;
|
|
142
343
|
async function fetchAllPages(fetchPage, baseParams) {
|
|
143
344
|
const items = [];
|
|
144
345
|
let cursor = null;
|
|
@@ -153,82 +354,284 @@ async function fetchAllPages(fetchPage, baseParams) {
|
|
|
153
354
|
} while (cursor);
|
|
154
355
|
return items;
|
|
155
356
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
357
|
+
|
|
358
|
+
// src/shared/core/utils/crypto.ts
|
|
359
|
+
async function sha256(data) {
|
|
360
|
+
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
361
|
+
const buffer = bytes.buffer.slice(
|
|
362
|
+
bytes.byteOffset,
|
|
363
|
+
bytes.byteOffset + bytes.byteLength
|
|
364
|
+
);
|
|
365
|
+
return crypto.subtle.digest("SHA-256", buffer);
|
|
366
|
+
}
|
|
367
|
+
function arrayBufferToBase64Url(buffer, padding = true) {
|
|
368
|
+
const bytes = new Uint8Array(buffer);
|
|
369
|
+
let binary = "";
|
|
370
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
371
|
+
binary += String.fromCharCode(bytes[i]);
|
|
372
|
+
}
|
|
373
|
+
let base64 = btoa(binary);
|
|
374
|
+
base64 = base64.replace(/\+/g, "-").replace(/\//g, "_");
|
|
375
|
+
if (!padding) {
|
|
376
|
+
base64 = base64.replace(/=+$/, "");
|
|
377
|
+
}
|
|
378
|
+
return base64;
|
|
379
|
+
}
|
|
380
|
+
function generateSecureRandomBase64Url(byteLength) {
|
|
381
|
+
const bytes = new Uint8Array(byteLength);
|
|
382
|
+
crypto.getRandomValues(bytes);
|
|
383
|
+
const buffer = bytes.buffer;
|
|
384
|
+
return arrayBufferToBase64Url(buffer, false);
|
|
385
|
+
}
|
|
386
|
+
function notBlankStringOrNull(value) {
|
|
387
|
+
if (value?.trim()) {
|
|
388
|
+
return value;
|
|
389
|
+
} else {
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// src/shared/types/oauth.ts
|
|
395
|
+
var AuthorizationCode = (value) => value;
|
|
396
|
+
var CodeVerifier = (value) => value;
|
|
397
|
+
var CodeChallenge = (value) => value;
|
|
398
|
+
var PKCEState = (value) => value;
|
|
399
|
+
var RedirectUri = (value) => value;
|
|
400
|
+
var ClientId = (value) => value;
|
|
401
|
+
var ClientSecret = (value) => value;
|
|
402
|
+
|
|
403
|
+
// src/shared/core/auth/pkce.ts
|
|
404
|
+
async function generatePKCEParams(config) {
|
|
405
|
+
const state = generateSecureRandomBase64Url(32);
|
|
406
|
+
const codeVerifier = generateSecureRandomBase64Url(32);
|
|
407
|
+
const codeChallengeRaw = await sha256(codeVerifier);
|
|
408
|
+
const codeChallenge = arrayBufferToBase64Url(codeChallengeRaw, false);
|
|
409
|
+
return {
|
|
410
|
+
clientId: config.clientId,
|
|
411
|
+
responseType: "code",
|
|
412
|
+
redirectUri: config.redirectUri,
|
|
413
|
+
codeChallenge: CodeChallenge(codeChallenge),
|
|
414
|
+
codeChallengeMethod: "S256",
|
|
415
|
+
state: PKCEState(state),
|
|
416
|
+
codeVerifier: CodeVerifier(codeVerifier)
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// src/shared/types/errors.ts
|
|
421
|
+
var NotImplementedError = class extends Error {
|
|
422
|
+
constructor(message = "Not implemented yet") {
|
|
423
|
+
super(message);
|
|
424
|
+
this.name = "NotImplementedError";
|
|
425
|
+
}
|
|
162
426
|
};
|
|
163
|
-
var
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
427
|
+
var NotAuthenticatedError = class extends Error {
|
|
428
|
+
constructor(message = "The user is not authenticated. Go through the OAuth flow first!") {
|
|
429
|
+
super(message);
|
|
430
|
+
this.name = "NotAuthenticatedError";
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
var ValidationError = class extends Error {
|
|
434
|
+
constructor(message) {
|
|
435
|
+
super(message);
|
|
436
|
+
this.name = "ValidationError";
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
var InvariantError = class extends Error {
|
|
440
|
+
constructor(message) {
|
|
441
|
+
super(message);
|
|
442
|
+
this.name = "InvariantError";
|
|
176
443
|
}
|
|
177
444
|
};
|
|
178
445
|
|
|
179
|
-
// src/shared/
|
|
180
|
-
var
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
{
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
446
|
+
// src/shared/types/blockchain/core.ts
|
|
447
|
+
var ETHEREUM_CHAINS = {
|
|
448
|
+
ethereum_mainnet: true,
|
|
449
|
+
ethereum_sepolia: true
|
|
450
|
+
};
|
|
451
|
+
var EthereumChain = (value) => {
|
|
452
|
+
if (!Object.keys(ETHEREUM_CHAINS).includes(value)) {
|
|
453
|
+
throw new ValidationError(`Unsupported Ethereum chain: "${value}"`);
|
|
454
|
+
}
|
|
455
|
+
return value;
|
|
456
|
+
};
|
|
457
|
+
var SOLANA_CHAINS = {
|
|
458
|
+
solana_mainnet: true,
|
|
459
|
+
solana_devnet: true
|
|
460
|
+
};
|
|
461
|
+
var SolanaChain = (value) => {
|
|
462
|
+
if (!Object.keys(SOLANA_CHAINS).includes(value)) {
|
|
463
|
+
throw new ValidationError(`Unsupported Solana chain: "${value}"`);
|
|
464
|
+
}
|
|
465
|
+
return value;
|
|
466
|
+
};
|
|
467
|
+
var Chain = (value) => {
|
|
468
|
+
if (!Object.keys(ETHEREUM_CHAINS).includes(value) && !Object.keys(SOLANA_CHAINS).includes(value)) {
|
|
469
|
+
throw new ValidationError(`Unsupported chain: "${value}"`);
|
|
470
|
+
}
|
|
471
|
+
return value;
|
|
472
|
+
};
|
|
473
|
+
var EvmWalletAddress = (value) => value;
|
|
474
|
+
var EvmContractAddress = (value) => value;
|
|
475
|
+
var HexEncodedTransactionData = (value) => value;
|
|
476
|
+
var MAX_ASSET_DECIMALS = 77;
|
|
477
|
+
var AssetDecimals = (value) => {
|
|
478
|
+
if (!Number.isInteger(value)) {
|
|
479
|
+
throw new ValidationError(`Asset decimals must be an integer: ${value}`);
|
|
480
|
+
}
|
|
481
|
+
if (value < 0 || value > MAX_ASSET_DECIMALS) {
|
|
482
|
+
throw new ValidationError(
|
|
483
|
+
`Asset decimals out of range [0, ${MAX_ASSET_DECIMALS}]: ${value}`
|
|
484
|
+
);
|
|
485
|
+
}
|
|
486
|
+
return value;
|
|
487
|
+
};
|
|
488
|
+
var STABLE_DECIMALS = AssetDecimals(6);
|
|
489
|
+
var DecimalString = (value) => value;
|
|
490
|
+
var MAX_UINT_256 = 2n ** 256n - 1n;
|
|
491
|
+
var assertUint256 = (value) => {
|
|
492
|
+
if (isUint256(value)) return value;
|
|
493
|
+
throw new InvariantError(`Value out of uint256 bounds: ${value}`);
|
|
494
|
+
};
|
|
495
|
+
var parseUint256 = (value, label) => {
|
|
496
|
+
if (isUint256(value)) return value;
|
|
497
|
+
throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
|
|
498
|
+
};
|
|
499
|
+
var isUint256 = (value) => value >= 0n && value <= MAX_UINT_256;
|
|
500
|
+
var BlockchainAmount = Object.assign(
|
|
501
|
+
(value) => value,
|
|
229
502
|
{
|
|
230
|
-
|
|
231
|
-
|
|
503
|
+
add: (a, b) => combineAmounts(a, b, (x, y) => x + y),
|
|
504
|
+
sub: (a, b) => combineAmounts(a, b, (x, y) => x - y)
|
|
505
|
+
}
|
|
506
|
+
);
|
|
507
|
+
function combineAmounts(a, b, op) {
|
|
508
|
+
if (a.decimals !== b.decimals) {
|
|
509
|
+
throw new InvariantError(
|
|
510
|
+
`Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
const raw = op(a.raw, b.raw);
|
|
514
|
+
if (raw < 0n || raw > MAX_UINT_256) {
|
|
515
|
+
throw new InvariantError(`BlockchainAmount out of uint256 bounds: ${raw}`);
|
|
516
|
+
}
|
|
517
|
+
return BlockchainAmount({ raw, decimals: a.decimals });
|
|
518
|
+
}
|
|
519
|
+
var AssetSymbol = (value) => value;
|
|
520
|
+
var StablecoinSymbol = (value) => value;
|
|
521
|
+
var KnownAssetSymbol = StablecoinSymbol;
|
|
522
|
+
var Bps = (value) => value;
|
|
523
|
+
|
|
524
|
+
// src/shared/core/blockchain/bps.ts
|
|
525
|
+
var BPS_DENOM = Bps(10000n);
|
|
526
|
+
function applyBps(amount, bps) {
|
|
527
|
+
return assertUint256(amount * bps / BPS_DENOM);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// src/shared/types/blockchain/ui.ts
|
|
531
|
+
var FormattedAmountUi = (value) => value;
|
|
532
|
+
var FormattedPercentUi = (value) => value;
|
|
533
|
+
var TxExplorerUrl = (value) => value;
|
|
534
|
+
var ShortenedWalletAddress = (value) => value;
|
|
535
|
+
var FormattedAmountAssetUi = (value) => value;
|
|
536
|
+
var AssetIconUrl = (value) => value;
|
|
537
|
+
|
|
538
|
+
// src/shared/core/blockchain/chain.ts
|
|
539
|
+
var CHAIN_IDS = {
|
|
540
|
+
ethereum_mainnet: 1,
|
|
541
|
+
ethereum_sepolia: 11155111
|
|
542
|
+
};
|
|
543
|
+
function getChainId(chain) {
|
|
544
|
+
return CHAIN_IDS[chain];
|
|
545
|
+
}
|
|
546
|
+
function chainFromId(chainId) {
|
|
547
|
+
const chains = Object.keys(CHAIN_IDS);
|
|
548
|
+
const chain = chains.find((c) => String(CHAIN_IDS[c]) === chainId);
|
|
549
|
+
if (!chain) {
|
|
550
|
+
throw new ValidationError(`Unsupported EIP-155 chain id: "${chainId}"`);
|
|
551
|
+
}
|
|
552
|
+
return chain;
|
|
553
|
+
}
|
|
554
|
+
function getNetworkName(chain) {
|
|
555
|
+
switch (chain) {
|
|
556
|
+
case "ethereum_mainnet":
|
|
557
|
+
return "Ethereum";
|
|
558
|
+
case "ethereum_sepolia":
|
|
559
|
+
return "Ethereum Sepolia";
|
|
560
|
+
default: {
|
|
561
|
+
const _exhaustive = chain;
|
|
562
|
+
return _exhaustive;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function txExplorerUrl(chain, txHash) {
|
|
567
|
+
return TxExplorerUrl(`${explorerBaseUrl(chain)}/tx/${txHash}`);
|
|
568
|
+
}
|
|
569
|
+
function explorerBaseUrl(chain) {
|
|
570
|
+
switch (chain) {
|
|
571
|
+
case "ethereum_mainnet":
|
|
572
|
+
return "https://etherscan.io";
|
|
573
|
+
case "ethereum_sepolia":
|
|
574
|
+
return "https://sepolia.etherscan.io";
|
|
575
|
+
default: {
|
|
576
|
+
const _exhaustive = chain;
|
|
577
|
+
return _exhaustive;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// src/shared/core/blockchain/erc20/abi.ts
|
|
583
|
+
var ERC20_ABI = [
|
|
584
|
+
{
|
|
585
|
+
type: "function",
|
|
586
|
+
name: "allowance",
|
|
587
|
+
inputs: [
|
|
588
|
+
{ name: "owner", type: "address" },
|
|
589
|
+
{ name: "spender", type: "address" }
|
|
590
|
+
],
|
|
591
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
592
|
+
stateMutability: "view"
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
type: "function",
|
|
596
|
+
name: "approve",
|
|
597
|
+
inputs: [
|
|
598
|
+
{ name: "spender", type: "address" },
|
|
599
|
+
{ name: "amount", type: "uint256" }
|
|
600
|
+
],
|
|
601
|
+
outputs: [{ name: "", type: "bool" }],
|
|
602
|
+
stateMutability: "nonpayable"
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
type: "function",
|
|
606
|
+
name: "balanceOf",
|
|
607
|
+
inputs: [{ name: "account", type: "address" }],
|
|
608
|
+
outputs: [{ name: "", type: "uint256" }],
|
|
609
|
+
stateMutability: "view"
|
|
610
|
+
},
|
|
611
|
+
{
|
|
612
|
+
type: "function",
|
|
613
|
+
name: "decimals",
|
|
614
|
+
inputs: [],
|
|
615
|
+
outputs: [{ name: "", type: "uint8" }],
|
|
616
|
+
stateMutability: "view"
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
type: "function",
|
|
620
|
+
name: "name",
|
|
621
|
+
inputs: [],
|
|
622
|
+
outputs: [{ name: "", type: "string" }],
|
|
623
|
+
stateMutability: "view"
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
type: "function",
|
|
627
|
+
name: "symbol",
|
|
628
|
+
inputs: [],
|
|
629
|
+
outputs: [{ name: "", type: "string" }],
|
|
630
|
+
stateMutability: "view"
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
type: "function",
|
|
634
|
+
name: "totalSupply",
|
|
232
635
|
inputs: [],
|
|
233
636
|
outputs: [{ name: "", type: "uint256" }],
|
|
234
637
|
stateMutability: "view"
|
|
@@ -274,9 +677,1041 @@ var ERC20_ABI = [
|
|
|
274
677
|
],
|
|
275
678
|
anonymous: false
|
|
276
679
|
}
|
|
277
|
-
];
|
|
680
|
+
];
|
|
681
|
+
|
|
682
|
+
// src/shared/types/providers/superstate/swap.ts
|
|
683
|
+
var SwapAuthorization = {
|
|
684
|
+
fromDto: (dto) => ({
|
|
685
|
+
authorized: dto.authorized
|
|
686
|
+
})
|
|
687
|
+
};
|
|
688
|
+
var SwapPreview = {
|
|
689
|
+
fromDto: (dto) => ({
|
|
690
|
+
inputAmount: parseUint256(
|
|
691
|
+
BigInt(dto.pay_input_amount),
|
|
692
|
+
"SwapPreview.pay_input_amount"
|
|
693
|
+
),
|
|
694
|
+
fee: parseUint256(BigInt(dto.fee), "SwapPreview.fee"),
|
|
695
|
+
outputAmount: parseUint256(
|
|
696
|
+
BigInt(dto.receive_output_amount),
|
|
697
|
+
"SwapPreview.receive_output_amount"
|
|
698
|
+
)
|
|
699
|
+
})
|
|
700
|
+
};
|
|
701
|
+
var SwapStatus = {
|
|
702
|
+
fromDto: (dto) => ({
|
|
703
|
+
stopped: parseUint256(BigInt(dto.stopped), "SwapStatus.stopped"),
|
|
704
|
+
swapLevel: parseUint256(BigInt(dto.swap_level), "SwapStatus.swap_level")
|
|
705
|
+
})
|
|
706
|
+
};
|
|
707
|
+
var TokenAllowance = {
|
|
708
|
+
fromDto: (dto) => ({
|
|
709
|
+
allowance: parseUint256(BigInt(dto.allowance), "TokenAllowance.allowance")
|
|
710
|
+
})
|
|
711
|
+
};
|
|
712
|
+
var TokenBalance = {
|
|
713
|
+
fromDto: (dto) => ({
|
|
714
|
+
balance: parseUint256(BigInt(dto.balance), "TokenBalance.balance")
|
|
715
|
+
})
|
|
716
|
+
};
|
|
717
|
+
var AllowWalletResponse = {
|
|
718
|
+
fromDto: (dto) => {
|
|
719
|
+
switch (dto.action) {
|
|
720
|
+
case "broadcast_transaction":
|
|
721
|
+
return {
|
|
722
|
+
action: "broadcast_transaction",
|
|
723
|
+
to: EvmContractAddress(dto.to),
|
|
724
|
+
data: HexEncodedTransactionData(dto.data)
|
|
725
|
+
};
|
|
726
|
+
case "none":
|
|
727
|
+
return {
|
|
728
|
+
action: "none",
|
|
729
|
+
alreadyAllowed: dto.already_allowed
|
|
730
|
+
};
|
|
731
|
+
default: {
|
|
732
|
+
const _exhaustive = dto;
|
|
733
|
+
return _exhaustive;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
};
|
|
738
|
+
|
|
739
|
+
// src/shared/api/frontline/providers/superstate/swap.ts
|
|
740
|
+
async function getSwapAuthorization(api, params) {
|
|
741
|
+
const dto = await api.send({
|
|
742
|
+
method: "GET",
|
|
743
|
+
url: "/v1/wallet/authorized",
|
|
744
|
+
queryParams: {
|
|
745
|
+
chain: params.chain,
|
|
746
|
+
contract_address: params.contractAddress,
|
|
747
|
+
wallet_address: params.walletAddress
|
|
748
|
+
},
|
|
749
|
+
attributes: Attributes.protected()
|
|
750
|
+
});
|
|
751
|
+
return SwapAuthorization.fromDto(dto);
|
|
752
|
+
}
|
|
753
|
+
async function getSwapOutputToken(api, params) {
|
|
754
|
+
const dto = await api.send({
|
|
755
|
+
method: "GET",
|
|
756
|
+
url: "/v1/swap/output-token",
|
|
757
|
+
queryParams: {
|
|
758
|
+
chain: params.chain,
|
|
759
|
+
contract_address: params.contractAddress
|
|
760
|
+
},
|
|
761
|
+
attributes: Attributes.protected()
|
|
762
|
+
});
|
|
763
|
+
return toErc20Asset(dto);
|
|
764
|
+
}
|
|
765
|
+
async function getSwapPreview(api, params) {
|
|
766
|
+
const dto = await api.send({
|
|
767
|
+
method: "GET",
|
|
768
|
+
url: "/v1/swap/preview",
|
|
769
|
+
queryParams: {
|
|
770
|
+
chain: params.chain,
|
|
771
|
+
contract_address: params.contractAddress,
|
|
772
|
+
input_token: params.inputToken,
|
|
773
|
+
amount: params.amount.toString()
|
|
774
|
+
},
|
|
775
|
+
attributes: Attributes.protected()
|
|
776
|
+
});
|
|
777
|
+
return SwapPreview.fromDto(dto);
|
|
778
|
+
}
|
|
779
|
+
async function getSwapStatus(api, params) {
|
|
780
|
+
const dto = await api.send({
|
|
781
|
+
method: "GET",
|
|
782
|
+
url: "/v1/swap/status",
|
|
783
|
+
queryParams: {
|
|
784
|
+
chain: params.chain,
|
|
785
|
+
contract_address: params.contractAddress
|
|
786
|
+
},
|
|
787
|
+
attributes: Attributes.protected()
|
|
788
|
+
});
|
|
789
|
+
return SwapStatus.fromDto(dto);
|
|
790
|
+
}
|
|
791
|
+
async function getTokenAllowance(api, params) {
|
|
792
|
+
const dto = await api.send({
|
|
793
|
+
method: "GET",
|
|
794
|
+
url: "/v1/token/allowance",
|
|
795
|
+
queryParams: {
|
|
796
|
+
chain: params.chain,
|
|
797
|
+
token_address: params.tokenAddress,
|
|
798
|
+
owner: params.owner,
|
|
799
|
+
spender: params.spender
|
|
800
|
+
},
|
|
801
|
+
attributes: Attributes.protected()
|
|
802
|
+
});
|
|
803
|
+
return TokenAllowance.fromDto(dto);
|
|
804
|
+
}
|
|
805
|
+
async function getTokenBalance(api, params) {
|
|
806
|
+
const dto = await api.send({
|
|
807
|
+
method: "GET",
|
|
808
|
+
url: "/v1/token/balance",
|
|
809
|
+
queryParams: {
|
|
810
|
+
chain: params.chain,
|
|
811
|
+
token_address: params.tokenAddress,
|
|
812
|
+
owner: params.owner
|
|
813
|
+
},
|
|
814
|
+
attributes: Attributes.protected()
|
|
815
|
+
});
|
|
816
|
+
return TokenBalance.fromDto(dto);
|
|
817
|
+
}
|
|
818
|
+
async function allowWallet(api, params) {
|
|
819
|
+
const dto = await api.send({
|
|
820
|
+
method: "POST",
|
|
821
|
+
url: `/v1/offers/${encodeURIComponent(params.offerId)}/allow-wallet`,
|
|
822
|
+
body: {
|
|
823
|
+
wallet_address: params.walletAddress,
|
|
824
|
+
chain: params.chain,
|
|
825
|
+
signature: params.signature
|
|
826
|
+
},
|
|
827
|
+
attributes: Attributes.protected()
|
|
828
|
+
});
|
|
829
|
+
return AllowWalletResponse.fromDto(dto);
|
|
830
|
+
}
|
|
831
|
+
function toErc20Asset(dto) {
|
|
832
|
+
return {
|
|
833
|
+
name: dto.name,
|
|
834
|
+
symbol: AssetSymbol(dto.symbol),
|
|
835
|
+
decimals: AssetDecimals(dto.decimals)
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
// src/shared/core/observability/log-cause.ts
|
|
840
|
+
function classifyLogCause(error) {
|
|
841
|
+
if (error instanceof HttpError) {
|
|
842
|
+
return httpCause(error);
|
|
843
|
+
}
|
|
844
|
+
if (error instanceof ValidationError) {
|
|
845
|
+
return { type: "validation", message: error.message };
|
|
846
|
+
}
|
|
847
|
+
if (error instanceof InvariantError) {
|
|
848
|
+
return { type: "invariant", message: error.message };
|
|
849
|
+
}
|
|
850
|
+
if (error instanceof NotAuthenticatedError) {
|
|
851
|
+
return { type: "not-authenticated" };
|
|
852
|
+
}
|
|
853
|
+
if (error instanceof NotImplementedError) {
|
|
854
|
+
return { type: "not-implemented" };
|
|
855
|
+
}
|
|
856
|
+
return { type: "generic-error", name: errorName(error) };
|
|
857
|
+
}
|
|
858
|
+
function describeErrorUnredacted(error) {
|
|
859
|
+
if (error instanceof HttpError) {
|
|
860
|
+
return describeHttpErrorRedacted(error);
|
|
861
|
+
}
|
|
862
|
+
if (error instanceof Error) {
|
|
863
|
+
return `${error.name}: ${error.message}`;
|
|
864
|
+
}
|
|
865
|
+
return `thrown non-error: ${stringifyUnredacted(error)}`;
|
|
866
|
+
}
|
|
867
|
+
function stringifyUnredacted(value) {
|
|
868
|
+
if (value === void 0) return "";
|
|
869
|
+
try {
|
|
870
|
+
return JSON.stringify(
|
|
871
|
+
value,
|
|
872
|
+
(_key, item) => typeof item === "bigint" ? `${item}` : item
|
|
873
|
+
) ?? String(value);
|
|
874
|
+
} catch (_) {
|
|
875
|
+
return "<unserializable>";
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
function describeHttpErrorRedacted(error) {
|
|
879
|
+
const code = apiErrorCode(error);
|
|
880
|
+
const status = error.response.status;
|
|
881
|
+
return code === null ? `HttpError ${status}` : `HttpError ${status} (${code})`;
|
|
882
|
+
}
|
|
883
|
+
function errorName(error) {
|
|
884
|
+
return error instanceof Error ? error.name : `non-error ${typeof error}`;
|
|
885
|
+
}
|
|
886
|
+
function httpCause(error) {
|
|
887
|
+
return {
|
|
888
|
+
type: "http",
|
|
889
|
+
requestId: error.requestId,
|
|
890
|
+
status: error.response.status,
|
|
891
|
+
code: apiErrorCode(error),
|
|
892
|
+
eventId: apiErrorEventId(error)
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
function apiErrorEventId(error) {
|
|
896
|
+
const body = error.response.body;
|
|
897
|
+
if (typeof body !== "object" || body === null) return null;
|
|
898
|
+
const eventId = body.event_id;
|
|
899
|
+
return typeof eventId === "string" ? eventId : null;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
// src/shared/core/observability/internal-logger.ts
|
|
903
|
+
function internalLogger(logger, scope) {
|
|
904
|
+
return logger ? scopedLogger(logger, scope, {}) : noopInternalLogger;
|
|
905
|
+
}
|
|
906
|
+
var LEVEL_RANK = {
|
|
907
|
+
none: 0,
|
|
908
|
+
error: 1,
|
|
909
|
+
warn: 2,
|
|
910
|
+
info: 3,
|
|
911
|
+
debug: 4
|
|
912
|
+
};
|
|
913
|
+
function scopedLogger(logger, scope, bindings) {
|
|
914
|
+
const admits = (level) => LEVEL_RANK[logger.level()] >= LEVEL_RANK[level];
|
|
915
|
+
const safe = (event) => ({
|
|
916
|
+
msg: event.msg,
|
|
917
|
+
scope,
|
|
918
|
+
bindings,
|
|
919
|
+
fields: event.fields ?? {},
|
|
920
|
+
...event.cause === void 0 ? {} : { cause: event.cause }
|
|
921
|
+
});
|
|
922
|
+
const unredacted = (event) => ({
|
|
923
|
+
msg: event.msg,
|
|
924
|
+
scope,
|
|
925
|
+
bindings,
|
|
926
|
+
fields: event.fields ?? {}
|
|
927
|
+
});
|
|
928
|
+
const self = {
|
|
929
|
+
child: (binding) => scopedLogger(logger, scope, { ...bindings, ...binding }),
|
|
930
|
+
debug: (event) => {
|
|
931
|
+
if (admits("debug")) logger.debug(() => unredacted(event()));
|
|
932
|
+
},
|
|
933
|
+
info: (event) => {
|
|
934
|
+
if (admits("info")) logger.info(() => safe(event()));
|
|
935
|
+
},
|
|
936
|
+
warn: (event) => {
|
|
937
|
+
if (admits("warn")) logger.warn(() => safe(event()));
|
|
938
|
+
},
|
|
939
|
+
error: (event) => {
|
|
940
|
+
if (admits("error")) logger.error(() => safe(event()));
|
|
941
|
+
},
|
|
942
|
+
failure: (event, error) => {
|
|
943
|
+
if (admits("debug"))
|
|
944
|
+
logger.debug(() => unredacted(verbatim(event(), error)));
|
|
945
|
+
if (admits("error")) logger.error(() => safe(classified(event(), error)));
|
|
946
|
+
},
|
|
947
|
+
warning: (event, error) => {
|
|
948
|
+
if (admits("debug"))
|
|
949
|
+
logger.debug(() => unredacted(verbatim(event(), error)));
|
|
950
|
+
if (admits("warn")) logger.warn(() => safe(classified(event(), error)));
|
|
951
|
+
},
|
|
952
|
+
wrap: async (op, params, run) => {
|
|
953
|
+
const opLog = self.child({ op });
|
|
954
|
+
opLog.debug(() => ({ msg: "call", fields: { params } }));
|
|
955
|
+
try {
|
|
956
|
+
return await run();
|
|
957
|
+
} catch (error) {
|
|
958
|
+
opLog.failure(() => ({ msg: "call failed" }), error);
|
|
959
|
+
throw error;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
return self;
|
|
964
|
+
}
|
|
965
|
+
function verbatim(event, error) {
|
|
966
|
+
return {
|
|
967
|
+
msg: event.msg,
|
|
968
|
+
fields: { ...event.fields, error: describeErrorUnredacted(error) }
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
function classified(event, error) {
|
|
972
|
+
return { ...event, cause: event.cause ?? classifyLogCause(error) };
|
|
973
|
+
}
|
|
974
|
+
var noopInternalLogger = {
|
|
975
|
+
child: () => noopInternalLogger,
|
|
976
|
+
debug: () => void 0,
|
|
977
|
+
info: () => void 0,
|
|
978
|
+
warn: () => void 0,
|
|
979
|
+
error: () => void 0,
|
|
980
|
+
failure: () => void 0,
|
|
981
|
+
warning: () => void 0,
|
|
982
|
+
wrap: (_op, _params, run) => run()
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
// src/shared/core/blockchain/erc20/erc20-namespace.ts
|
|
986
|
+
var Erc20NamespaceImpl = class {
|
|
987
|
+
constructor(ctx) {
|
|
988
|
+
this.ctx = ctx;
|
|
989
|
+
this.log = internalLogger(ctx.logger, "ERC20");
|
|
990
|
+
}
|
|
991
|
+
async getAllowance(params) {
|
|
992
|
+
return this.log.wrap("getAllowance", params, async () => {
|
|
993
|
+
await this.ctx.ensureUserAuthenticated();
|
|
994
|
+
return getTokenAllowance(this.ctx.api, params);
|
|
995
|
+
});
|
|
996
|
+
}
|
|
997
|
+
async getBalance(params) {
|
|
998
|
+
return this.log.wrap("getBalance", params, async () => {
|
|
999
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1000
|
+
return getTokenBalance(this.ctx.api, params);
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
// src/shared/core/blockchain/formatters.ts
|
|
1006
|
+
var import_viem = require("viem");
|
|
1007
|
+
function shortenAddress(address) {
|
|
1008
|
+
const short = address.length > 10 ? `${address.slice(0, 6)}\u2026${address.slice(-4)}` : address;
|
|
1009
|
+
return ShortenedWalletAddress(short);
|
|
1010
|
+
}
|
|
1011
|
+
function formatAmount(amount, locale, options) {
|
|
1012
|
+
const decimal = formatRawAmount(amount);
|
|
1013
|
+
let [integerPart, fractionPart = ""] = decimal.split(".");
|
|
1014
|
+
const maxFractionDigits = options?.maxFractionDigits;
|
|
1015
|
+
const minFractionDigits = maxFractionDigits !== void 0 ? Math.min(maxFractionDigits, amount.decimals) : Math.min(2, amount.decimals);
|
|
1016
|
+
if (maxFractionDigits !== void 0 && fractionPart.length > maxFractionDigits) {
|
|
1017
|
+
({ integerPart, fractionPart } = roundFractionHalfUp(
|
|
1018
|
+
integerPart,
|
|
1019
|
+
fractionPart,
|
|
1020
|
+
maxFractionDigits
|
|
1021
|
+
));
|
|
1022
|
+
}
|
|
1023
|
+
const fraction = minFractionDigits === 0 ? "" : fractionPart.padEnd(minFractionDigits, "0");
|
|
1024
|
+
const integerFormatted = BigInt(integerPart).toLocaleString(locale);
|
|
1025
|
+
if (minFractionDigits === 0 && fraction === "") {
|
|
1026
|
+
return FormattedAmountUi(integerFormatted);
|
|
1027
|
+
}
|
|
1028
|
+
const decimalSeparator = new Intl.NumberFormat(locale).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
|
|
1029
|
+
return FormattedAmountUi(`${integerFormatted}${decimalSeparator}${fraction}`);
|
|
1030
|
+
}
|
|
1031
|
+
function roundFractionHalfUp(integerPart, fractionPart, maxFractionDigits) {
|
|
1032
|
+
if (fractionPart.length <= maxFractionDigits) {
|
|
1033
|
+
return { integerPart, fractionPart };
|
|
1034
|
+
}
|
|
1035
|
+
if (maxFractionDigits === 0) {
|
|
1036
|
+
const roundUp = fractionPart[0] >= "5";
|
|
1037
|
+
const integer = BigInt(integerPart) + (roundUp ? 1n : 0n);
|
|
1038
|
+
return { integerPart: integer.toString(), fractionPart: "" };
|
|
1039
|
+
}
|
|
1040
|
+
const trimmed = fractionPart.slice(0, maxFractionDigits);
|
|
1041
|
+
if (fractionPart[maxFractionDigits] < "5") {
|
|
1042
|
+
return { integerPart, fractionPart: trimmed };
|
|
1043
|
+
}
|
|
1044
|
+
const digits = trimmed.split("").map((digit) => Number.parseInt(digit, 10));
|
|
1045
|
+
let carry = 1;
|
|
1046
|
+
for (let i = digits.length - 1; i >= 0 && carry > 0; i -= 1) {
|
|
1047
|
+
const sum = digits[i] + carry;
|
|
1048
|
+
if (sum === 10) {
|
|
1049
|
+
digits[i] = 0;
|
|
1050
|
+
carry = 1;
|
|
1051
|
+
} else {
|
|
1052
|
+
digits[i] = sum;
|
|
1053
|
+
carry = 0;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
return {
|
|
1057
|
+
integerPart: carry > 0 ? (BigInt(integerPart) + 1n).toString() : integerPart,
|
|
1058
|
+
fractionPart: digits.join("")
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
function formatRawAmount(amount) {
|
|
1062
|
+
return (0, import_viem.formatUnits)(amount.raw, amount.decimals);
|
|
1063
|
+
}
|
|
1064
|
+
function formatCompactAmount(amount, locale) {
|
|
1065
|
+
const value = Number(formatRawAmount(amount));
|
|
1066
|
+
const formatted = new Intl.NumberFormat(locale, {
|
|
1067
|
+
notation: "compact",
|
|
1068
|
+
maximumFractionDigits: 2
|
|
1069
|
+
}).format(value);
|
|
1070
|
+
return FormattedAmountUi(formatted);
|
|
1071
|
+
}
|
|
1072
|
+
function formatBpsAsPercent(bps, locale) {
|
|
1073
|
+
const whole = bps / 100n;
|
|
1074
|
+
const fraction = bps % 100n;
|
|
1075
|
+
const wholeFormatted = whole.toLocaleString(locale);
|
|
1076
|
+
const decimalSeparator = new Intl.NumberFormat(locale).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
|
|
1077
|
+
if (fraction === 0n) {
|
|
1078
|
+
return FormattedPercentUi(`${wholeFormatted}%`);
|
|
1079
|
+
}
|
|
1080
|
+
const fractionFormatted = fraction.toString().padStart(2, "0").replace(/0+$/, "");
|
|
1081
|
+
return FormattedPercentUi(
|
|
1082
|
+
`${wholeFormatted}${decimalSeparator}${fractionFormatted}%`
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
function usdAmount(amount) {
|
|
1086
|
+
return FormattedAmountAssetUi(`$${amount}`);
|
|
1087
|
+
}
|
|
1088
|
+
function assetAmount(amount, symbol) {
|
|
1089
|
+
return FormattedAmountAssetUi(`${amount} ${symbol}`);
|
|
1090
|
+
}
|
|
1091
|
+
var NA_AMOUNT_ASSET_UI = FormattedAmountAssetUi("-");
|
|
1092
|
+
var USD_FRACTION_DIGITS = AssetDecimals(2);
|
|
1093
|
+
function formattedUsdPrice(amount, locale) {
|
|
1094
|
+
if (!amount) return NA_AMOUNT_ASSET_UI;
|
|
1095
|
+
return usdAmount(
|
|
1096
|
+
formatAmount(amount, locale, { maxFractionDigits: USD_FRACTION_DIGITS })
|
|
1097
|
+
);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// src/shared/core/blockchain/math.ts
|
|
1101
|
+
var import_viem2 = require("viem");
|
|
1102
|
+
function blockchainAmountFromRawOrThrow({
|
|
1103
|
+
label,
|
|
1104
|
+
raw,
|
|
1105
|
+
decimals
|
|
1106
|
+
}) {
|
|
1107
|
+
const trimmed = raw.trim();
|
|
1108
|
+
if (trimmed === "") {
|
|
1109
|
+
throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
|
|
1110
|
+
}
|
|
1111
|
+
let value;
|
|
1112
|
+
try {
|
|
1113
|
+
value = BigInt(trimmed);
|
|
1114
|
+
} catch {
|
|
1115
|
+
throw new ValidationError(`${label}: not a uint256 integer ("${raw}")`);
|
|
1116
|
+
}
|
|
1117
|
+
try {
|
|
1118
|
+
return BlockchainAmount({ raw: assertUint256(value), decimals });
|
|
1119
|
+
} catch {
|
|
1120
|
+
throw new ValidationError(`${label}: out of uint256 bounds (${value})`);
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
function parseBlockchainAmount(amount, decimals) {
|
|
1124
|
+
const trimmed = amount.trim();
|
|
1125
|
+
if (trimmed === "") return { valid: false, reason: { type: "empty" } };
|
|
1126
|
+
if (trimmed.startsWith("-")) {
|
|
1127
|
+
return { valid: false, reason: { type: "negative" } };
|
|
1128
|
+
}
|
|
1129
|
+
if (/[eE]/.test(trimmed)) {
|
|
1130
|
+
return { valid: false, reason: { type: "invalid-format" } };
|
|
1131
|
+
}
|
|
1132
|
+
if (!/^\d+(\.\d+)?$/.test(trimmed)) {
|
|
1133
|
+
return { valid: false, reason: { type: "invalid-format" } };
|
|
1134
|
+
}
|
|
1135
|
+
const [, fraction = ""] = trimmed.split(".");
|
|
1136
|
+
if (fraction.length > decimals) {
|
|
1137
|
+
return {
|
|
1138
|
+
valid: false,
|
|
1139
|
+
reason: { type: "too-many-decimals", maxDecimals: decimals }
|
|
1140
|
+
};
|
|
1141
|
+
}
|
|
1142
|
+
try {
|
|
1143
|
+
const raw = (0, import_viem2.parseUnits)(trimmed, decimals);
|
|
1144
|
+
if (raw > MAX_UINT_256) {
|
|
1145
|
+
return { valid: false, reason: { type: "overflow" } };
|
|
1146
|
+
}
|
|
1147
|
+
return {
|
|
1148
|
+
valid: true,
|
|
1149
|
+
amount: BlockchainAmount({ raw, decimals })
|
|
1150
|
+
};
|
|
1151
|
+
} catch {
|
|
1152
|
+
return { valid: false, reason: { type: "invalid-format" } };
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
// src/shared/core/blockchain/token-registry.ts
|
|
1157
|
+
var USDC_SYMBOL = StablecoinSymbol("USDC");
|
|
1158
|
+
var USDC = {
|
|
1159
|
+
name: "USD Coin",
|
|
1160
|
+
symbol: USDC_SYMBOL,
|
|
1161
|
+
decimals: AssetDecimals(6)
|
|
1162
|
+
};
|
|
1163
|
+
var USDT_SYMBOL = StablecoinSymbol("USDT");
|
|
1164
|
+
var USDT = {
|
|
1165
|
+
name: "Tether USD",
|
|
1166
|
+
symbol: USDT_SYMBOL,
|
|
1167
|
+
decimals: AssetDecimals(6)
|
|
1168
|
+
};
|
|
1169
|
+
var USDC_ADDRESSES = {
|
|
1170
|
+
ethereum_mainnet: EvmContractAddress(
|
|
1171
|
+
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
|
1172
|
+
),
|
|
1173
|
+
ethereum_sepolia: EvmContractAddress(
|
|
1174
|
+
"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
|
|
1175
|
+
)
|
|
1176
|
+
};
|
|
1177
|
+
var USDT_ADDRESSES = {
|
|
1178
|
+
ethereum_mainnet: EvmContractAddress(
|
|
1179
|
+
"0xdac17f958d2ee523a2206206994597c13d831ec7"
|
|
1180
|
+
),
|
|
1181
|
+
ethereum_sepolia: EvmContractAddress(
|
|
1182
|
+
"0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
1183
|
+
)
|
|
1184
|
+
};
|
|
1185
|
+
var TOKEN_REGISTRY = {
|
|
1186
|
+
erc20: (symbol) => {
|
|
1187
|
+
switch (symbol) {
|
|
1188
|
+
case "USDC":
|
|
1189
|
+
return USDC;
|
|
1190
|
+
case "USDT":
|
|
1191
|
+
return USDT;
|
|
1192
|
+
default:
|
|
1193
|
+
throw new InvariantError(`Unknown asset symbol: ${symbol}`);
|
|
1194
|
+
}
|
|
1195
|
+
},
|
|
1196
|
+
contractAddress: (symbol, chain) => {
|
|
1197
|
+
switch (symbol) {
|
|
1198
|
+
case "USDC":
|
|
1199
|
+
return USDC_ADDRESSES[chain];
|
|
1200
|
+
case "USDT":
|
|
1201
|
+
return USDT_ADDRESSES[chain];
|
|
1202
|
+
default:
|
|
1203
|
+
throw new InvariantError(`Unknown asset symbol: ${symbol}`);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
};
|
|
1207
|
+
|
|
1208
|
+
// src/shared/types/pagination.ts
|
|
1209
|
+
var Cursor = (value) => value;
|
|
1210
|
+
var PaginatedResponse = {
|
|
1211
|
+
fromDto: (dto, itemMapper) => ({
|
|
1212
|
+
data: dto.data.map(itemMapper),
|
|
1213
|
+
startingAfter: dto.starting_after ? Cursor(dto.starting_after) : null,
|
|
1214
|
+
startingBefore: dto.starting_before ? Cursor(dto.starting_before) : null
|
|
1215
|
+
})
|
|
1216
|
+
};
|
|
1217
|
+
var PaginationParams = {
|
|
1218
|
+
toQueryParams: (params) => {
|
|
1219
|
+
const queryParams = {};
|
|
1220
|
+
if (params.after) {
|
|
1221
|
+
queryParams.starting_after = params.after;
|
|
1222
|
+
}
|
|
1223
|
+
if (params.before) {
|
|
1224
|
+
queryParams.starting_before = params.before;
|
|
1225
|
+
}
|
|
1226
|
+
if (params.limit) {
|
|
1227
|
+
queryParams.limit = params.limit;
|
|
1228
|
+
}
|
|
1229
|
+
return queryParams;
|
|
1230
|
+
}
|
|
1231
|
+
};
|
|
1232
|
+
|
|
1233
|
+
// src/shared/types/asset.ts
|
|
1234
|
+
var AssetId = (value) => value;
|
|
1235
|
+
var AssetCode = (value) => value;
|
|
1236
|
+
var Asset = {
|
|
1237
|
+
fromDto: (dto) => ({
|
|
1238
|
+
id: AssetId(dto.id),
|
|
1239
|
+
code: AssetCode(dto.code),
|
|
1240
|
+
name: dto.name,
|
|
1241
|
+
fractionalDigits: dto.fractional_digits
|
|
1242
|
+
})
|
|
1243
|
+
};
|
|
1244
|
+
|
|
1245
|
+
// src/shared/types/offer.ts
|
|
1246
|
+
var OfferId = (value) => value;
|
|
1247
|
+
var OfferSlug = (value) => value;
|
|
1248
|
+
var Offer = {
|
|
1249
|
+
fromDto: (dto) => {
|
|
1250
|
+
if (!Array.isArray(dto.tokens)) {
|
|
1251
|
+
throw new ValidationError(
|
|
1252
|
+
`Offer.tokens: expected an array, got ${typeof dto.tokens}`
|
|
1253
|
+
);
|
|
1254
|
+
}
|
|
1255
|
+
return {
|
|
1256
|
+
id: OfferId(dto.id),
|
|
1257
|
+
slug: OfferSlug(dto.slug),
|
|
1258
|
+
type: dto.type,
|
|
1259
|
+
tagline: dto.tagline,
|
|
1260
|
+
bannerUrl: dto.banner_url,
|
|
1261
|
+
logoUrl: dto.logo_url,
|
|
1262
|
+
startsAt: new Date(dto.starts_at),
|
|
1263
|
+
endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
|
|
1264
|
+
tokens: dto.tokens.map(OfferToken.fromDto)
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
};
|
|
1268
|
+
var OfferToken = {
|
|
1269
|
+
fromDto: (dto) => ({
|
|
1270
|
+
role: dto.role,
|
|
1271
|
+
chain: Chain(dto.chain),
|
|
1272
|
+
address: EvmContractAddress(dto.address)
|
|
1273
|
+
})
|
|
1274
|
+
};
|
|
1275
|
+
|
|
1276
|
+
// src/shared/types/offer-detail.ts
|
|
1277
|
+
var OfferOptionId = (value) => value;
|
|
1278
|
+
var OfferOptionSlug = (value) => value;
|
|
1279
|
+
var OfferDetail = {
|
|
1280
|
+
fromDto: (dto) => {
|
|
1281
|
+
if (!Array.isArray(dto.funding_assets)) {
|
|
1282
|
+
throw new ValidationError(
|
|
1283
|
+
`OfferDetail.funding_assets: expected an array, got ${typeof dto.funding_assets}`
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1286
|
+
if (!Array.isArray(dto.options)) {
|
|
1287
|
+
throw new ValidationError(
|
|
1288
|
+
`OfferDetail.options: expected an array, got ${typeof dto.options}`
|
|
1289
|
+
);
|
|
1290
|
+
}
|
|
1291
|
+
if (!Array.isArray(dto.terms)) {
|
|
1292
|
+
throw new ValidationError(
|
|
1293
|
+
`OfferDetail.terms: expected an array, got ${typeof dto.terms}`
|
|
1294
|
+
);
|
|
1295
|
+
}
|
|
1296
|
+
if (!Array.isArray(dto.links)) {
|
|
1297
|
+
throw new ValidationError(
|
|
1298
|
+
`OfferDetail.links: expected an array, got ${typeof dto.links}`
|
|
1299
|
+
);
|
|
1300
|
+
}
|
|
1301
|
+
if (!Array.isArray(dto.faqs)) {
|
|
1302
|
+
throw new ValidationError(
|
|
1303
|
+
`OfferDetail.faqs: expected an array, got ${typeof dto.faqs}`
|
|
1304
|
+
);
|
|
1305
|
+
}
|
|
1306
|
+
if (!Array.isArray(dto.milestones)) {
|
|
1307
|
+
throw new ValidationError(
|
|
1308
|
+
`OfferDetail.milestones: expected an array, got ${typeof dto.milestones}`
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
if (!Array.isArray(dto.tokens)) {
|
|
1312
|
+
throw new ValidationError(
|
|
1313
|
+
`OfferDetail.tokens: expected an array, got ${typeof dto.tokens}`
|
|
1314
|
+
);
|
|
1315
|
+
}
|
|
1316
|
+
return {
|
|
1317
|
+
id: OfferId(dto.id),
|
|
1318
|
+
slug: OfferSlug(dto.slug),
|
|
1319
|
+
type: dto.type,
|
|
1320
|
+
name: dto.name,
|
|
1321
|
+
asset: Asset.fromDto(dto.asset),
|
|
1322
|
+
fundingAssets: dto.funding_assets.map(Asset.fromDto),
|
|
1323
|
+
tokens: dto.tokens.map(OfferToken.fromDto),
|
|
1324
|
+
about: notBlankStringOrNull(dto.about),
|
|
1325
|
+
tagline: dto.tagline,
|
|
1326
|
+
bannerUrl: dto.banner_url,
|
|
1327
|
+
logoUrl: dto.logo_url,
|
|
1328
|
+
category: dto.category,
|
|
1329
|
+
startsAt: new Date(dto.starts_at),
|
|
1330
|
+
endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
|
|
1331
|
+
faqs: dto.faqs.map(FaqItem.fromDto),
|
|
1332
|
+
links: dto.links.map(Link.fromDto),
|
|
1333
|
+
milestones: dto.milestones.map(Milestone.fromDto),
|
|
1334
|
+
options: dto.options.map(OfferOption.fromDto),
|
|
1335
|
+
terms: dto.terms.map(TermItem.fromDto)
|
|
1336
|
+
};
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
var OfferOption = {
|
|
1340
|
+
fromDto: (dto) => ({
|
|
1341
|
+
id: OfferOptionId(dto.id),
|
|
1342
|
+
slug: OfferOptionSlug(dto.slug),
|
|
1343
|
+
bidIncrement: dto.bid_increment,
|
|
1344
|
+
floorPriceUsd: dto.floor_price_usd,
|
|
1345
|
+
minimumPurchaseUsd: dto.minimum_purchase_usd,
|
|
1346
|
+
priceUsd: dto.price_usd,
|
|
1347
|
+
saleAgreementUrl: notBlankStringOrNull(dto.sale_agreement_url),
|
|
1348
|
+
totalTokenSupply: dto.total_token_supply
|
|
1349
|
+
})
|
|
1350
|
+
};
|
|
1351
|
+
var FaqItem = {
|
|
1352
|
+
fromDto: (dto) => ({
|
|
1353
|
+
question: notBlankStringOrNull(dto.question),
|
|
1354
|
+
answer: notBlankStringOrNull(dto.answer)
|
|
1355
|
+
})
|
|
1356
|
+
};
|
|
1357
|
+
var Link = {
|
|
1358
|
+
fromDto: (dto) => ({
|
|
1359
|
+
label: notBlankStringOrNull(dto.label),
|
|
1360
|
+
url: notBlankStringOrNull(dto.url)
|
|
1361
|
+
})
|
|
1362
|
+
};
|
|
1363
|
+
var TermItem = {
|
|
1364
|
+
fromDto: (dto) => ({
|
|
1365
|
+
key: notBlankStringOrNull(dto.key),
|
|
1366
|
+
value: notBlankStringOrNull(dto.value)
|
|
1367
|
+
})
|
|
1368
|
+
};
|
|
1369
|
+
var Milestone = {
|
|
1370
|
+
fromDto: (dto) => ({
|
|
1371
|
+
name: notBlankStringOrNull(dto.name),
|
|
1372
|
+
schedule: notBlankStringOrNull(dto.schedule),
|
|
1373
|
+
status: dto.status
|
|
1374
|
+
})
|
|
1375
|
+
};
|
|
1376
|
+
|
|
1377
|
+
// src/shared/types/providers/coin-list/token-sale.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
|
+
// src/shared/api/frontline/providers/coin-list/token-sale.ts
|
|
1425
|
+
async function fetchParticipations(api, offerId) {
|
|
1426
|
+
return fetchAllPages(
|
|
1427
|
+
(params) => fetchParticipationsPage(api, params),
|
|
1428
|
+
{ offerId }
|
|
1429
|
+
);
|
|
1430
|
+
}
|
|
1431
|
+
async function fetchParticipationsPage(api, params) {
|
|
1432
|
+
const pageDto = await api.send({
|
|
1433
|
+
method: "GET",
|
|
1434
|
+
url: "/v1/participations",
|
|
1435
|
+
queryParams: ParticipationsPaginationParams.toQueryParams(params),
|
|
1436
|
+
attributes: Attributes.protected()
|
|
1437
|
+
});
|
|
1438
|
+
return PaginatedResponse.fromDto(pageDto, Participation.fromDto);
|
|
1439
|
+
}
|
|
1440
|
+
async function fetchParticipation(api, id) {
|
|
1441
|
+
const dto = await api.send({
|
|
1442
|
+
method: "GET",
|
|
1443
|
+
url: `/v1/participations/${id}`,
|
|
1444
|
+
attributes: Attributes.protected()
|
|
1445
|
+
});
|
|
1446
|
+
return Participation.fromDto(dto);
|
|
1447
|
+
}
|
|
1448
|
+
async function createParticipation(api, params) {
|
|
1449
|
+
const dto = await api.send({
|
|
1450
|
+
method: "POST",
|
|
1451
|
+
url: "/v1/participations",
|
|
1452
|
+
body: CreateParticipationParams.toDto(params),
|
|
1453
|
+
attributes: Attributes.protected()
|
|
1454
|
+
});
|
|
1455
|
+
return Participation.fromDto(dto);
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
// src/shared/core/checkout/coin-list/token-sale-namespace.ts
|
|
1459
|
+
var CoinListTokenSaleNamespaceImpl = class {
|
|
1460
|
+
constructor(ctx) {
|
|
1461
|
+
this.ctx = ctx;
|
|
1462
|
+
this.log = internalLogger(ctx.logger, "TOKEN_SALE");
|
|
1463
|
+
}
|
|
1464
|
+
async list(offerId) {
|
|
1465
|
+
return this.log.wrap("list", offerId, async () => {
|
|
1466
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1467
|
+
return fetchParticipations(this.ctx.api, offerId);
|
|
1468
|
+
});
|
|
1469
|
+
}
|
|
1470
|
+
async listPage(params) {
|
|
1471
|
+
return this.log.wrap("listPage", params, async () => {
|
|
1472
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1473
|
+
return fetchParticipationsPage(this.ctx.api, params);
|
|
1474
|
+
});
|
|
1475
|
+
}
|
|
1476
|
+
async get(id) {
|
|
1477
|
+
return this.log.wrap("get", id, async () => {
|
|
1478
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1479
|
+
return fetchParticipation(this.ctx.api, id);
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1482
|
+
async createParticipation(params) {
|
|
1483
|
+
return this.log.wrap("createParticipation", params, async () => {
|
|
1484
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1485
|
+
return createParticipation(this.ctx.api, params);
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
};
|
|
1489
|
+
|
|
1490
|
+
// src/shared/core/checkout/ondo/constants.ts
|
|
1491
|
+
var ONDO_SWAP_CONTRACT_ADDRESSES = {
|
|
1492
|
+
ethereum_sepolia: EvmContractAddress(
|
|
1493
|
+
"0x7014019ed51Edab984a71D30F2707D2dB2316A7A"
|
|
1494
|
+
)
|
|
1495
|
+
};
|
|
1496
|
+
function ondoSwapContractAddress(chain) {
|
|
1497
|
+
return ONDO_SWAP_CONTRACT_ADDRESSES[chain] ?? null;
|
|
1498
|
+
}
|
|
1499
|
+
var ONDO_POLL_INTERVAL_MS = 15e3;
|
|
1500
|
+
var ONDO_QUOTE_EXPIRY_THRESHOLD_MS = 5e3;
|
|
1501
|
+
var DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE = DecimalString("1000");
|
|
1502
|
+
var ONDO_SUPPORTED_INPUT_ASSETS = [
|
|
1503
|
+
USDC_SYMBOL
|
|
1504
|
+
];
|
|
1505
|
+
|
|
1506
|
+
// src/shared/core/checkout/ondo/math.ts
|
|
1507
|
+
function computeOndoPrice(transaction) {
|
|
1508
|
+
const { notionalValue, receiveOutputAmount } = transaction;
|
|
1509
|
+
if (receiveOutputAmount.raw <= 0n) {
|
|
1510
|
+
throw new ValidationError(
|
|
1511
|
+
"Ondo price: receiveOutputAmount must be greater than zero"
|
|
1512
|
+
);
|
|
1513
|
+
}
|
|
1514
|
+
const scaled = notionalValue.raw * 10n ** BigInt(receiveOutputAmount.decimals);
|
|
1515
|
+
const raw = scaled / receiveOutputAmount.raw;
|
|
1516
|
+
return BlockchainAmount({
|
|
1517
|
+
raw: assertPriceFits(raw),
|
|
1518
|
+
decimals: notionalValue.decimals
|
|
1519
|
+
});
|
|
1520
|
+
}
|
|
1521
|
+
function assertPriceFits(raw) {
|
|
1522
|
+
try {
|
|
1523
|
+
return assertUint256(raw);
|
|
1524
|
+
} catch {
|
|
1525
|
+
throw new ValidationError(`Ondo price: out of uint256 bounds (${raw})`);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
// src/shared/types/trading.ts
|
|
1530
|
+
var Ticker = (value) => value;
|
|
1531
|
+
|
|
1532
|
+
// src/shared/types/providers/ondo/ondo.ts
|
|
1533
|
+
var OndoTradingStatus = {
|
|
1534
|
+
fromDto: (dto) => {
|
|
1535
|
+
if (!dto.tradable) return { type: "not-tradable", side: dto.side };
|
|
1536
|
+
return {
|
|
1537
|
+
type: "tradable",
|
|
1538
|
+
side: dto.side,
|
|
1539
|
+
grossMaxTokens: decimalOrNull(dto.gross_max_tokens),
|
|
1540
|
+
grossMaxNotionalValue: decimalOrNull(dto.gross_max_notional_value),
|
|
1541
|
+
grossMaxActiveNotionalValue: decimalOrNull(
|
|
1542
|
+
dto.gross_max_active_notional_value
|
|
1543
|
+
)
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
var decimalOrNull = (value) => value === null ? null : DecimalString(value);
|
|
1548
|
+
var OndoQuote = {
|
|
1549
|
+
fromDto: (dto) => {
|
|
1550
|
+
const assetDecimals = AssetDecimals(dto.asset_decimals);
|
|
1551
|
+
return {
|
|
1552
|
+
chain: chainFromId(dto.chain_id),
|
|
1553
|
+
ticker: Ticker(dto.ticker),
|
|
1554
|
+
assetAddress: EvmContractAddress(dto.asset_address),
|
|
1555
|
+
asset: {
|
|
1556
|
+
name: dto.ticker,
|
|
1557
|
+
symbol: AssetSymbol(dto.symbol),
|
|
1558
|
+
decimals: assetDecimals
|
|
1559
|
+
},
|
|
1560
|
+
side: dto.side,
|
|
1561
|
+
tokenBaseUnits: blockchainAmountFromRawOrThrow({
|
|
1562
|
+
label: "tokenBaseUnits",
|
|
1563
|
+
raw: dto.token_base_units,
|
|
1564
|
+
decimals: assetDecimals
|
|
1565
|
+
}),
|
|
1566
|
+
price: DecimalString(dto.price)
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
};
|
|
1570
|
+
var OndoSwapTransaction = {
|
|
1571
|
+
fromDto: (dto) => {
|
|
1572
|
+
const inputDecimals = AssetDecimals(dto.pay_input_decimals);
|
|
1573
|
+
const outputDecimals = AssetDecimals(dto.receive_output_decimals);
|
|
1574
|
+
return {
|
|
1575
|
+
tx: {
|
|
1576
|
+
to: EvmContractAddress(dto.to),
|
|
1577
|
+
data: HexEncodedTransactionData(dto.data)
|
|
1578
|
+
},
|
|
1579
|
+
expiresAt: parseExpiresAt(dto.expires_at),
|
|
1580
|
+
payInputAmount: blockchainAmountFromRawOrThrow({
|
|
1581
|
+
label: "pay_input_amount",
|
|
1582
|
+
raw: dto.pay_input_amount,
|
|
1583
|
+
decimals: inputDecimals
|
|
1584
|
+
}),
|
|
1585
|
+
fee: blockchainAmountFromRawOrThrow({
|
|
1586
|
+
label: "fee",
|
|
1587
|
+
raw: dto.fee,
|
|
1588
|
+
decimals: inputDecimals
|
|
1589
|
+
}),
|
|
1590
|
+
notionalValue: blockchainAmountFromRawOrThrow({
|
|
1591
|
+
label: "notional_value",
|
|
1592
|
+
raw: dto.notional_value,
|
|
1593
|
+
decimals: inputDecimals
|
|
1594
|
+
}),
|
|
1595
|
+
receiveOutputAmount: parseReceiveOutputAmount(
|
|
1596
|
+
dto.receive_output_amount,
|
|
1597
|
+
outputDecimals
|
|
1598
|
+
)
|
|
1599
|
+
};
|
|
1600
|
+
}
|
|
1601
|
+
};
|
|
1602
|
+
function parseReceiveOutputAmount(raw, decimals) {
|
|
1603
|
+
const amount = blockchainAmountFromRawOrThrow({
|
|
1604
|
+
label: "receive_output_amount",
|
|
1605
|
+
raw,
|
|
1606
|
+
decimals
|
|
1607
|
+
});
|
|
1608
|
+
if (amount.raw <= 0n) {
|
|
1609
|
+
throw new ValidationError(
|
|
1610
|
+
`receive_output_amount: must be greater than zero ("${raw}")`
|
|
1611
|
+
);
|
|
1612
|
+
}
|
|
1613
|
+
return amount;
|
|
1614
|
+
}
|
|
1615
|
+
function parseExpiresAt(value) {
|
|
1616
|
+
const date = new Date(value);
|
|
1617
|
+
if (Number.isNaN(date.getTime())) {
|
|
1618
|
+
throw new ValidationError(`expires_at: not a date ("${value}")`);
|
|
1619
|
+
}
|
|
1620
|
+
return date;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
// src/shared/api/frontline/providers/ondo/ondo.ts
|
|
1624
|
+
async function getOndoTradingStatus(api, params) {
|
|
1625
|
+
const dto = await api.send({
|
|
1626
|
+
method: "GET",
|
|
1627
|
+
url: "/v1/ondo/swap/trading-status",
|
|
1628
|
+
queryParams: { symbol: params.symbol, side: params.side },
|
|
1629
|
+
attributes: Attributes.protected()
|
|
1630
|
+
});
|
|
1631
|
+
return OndoTradingStatus.fromDto(dto);
|
|
1632
|
+
}
|
|
1633
|
+
async function getOndoQuote(api, params) {
|
|
1634
|
+
const dto = await api.send({
|
|
1635
|
+
method: "GET",
|
|
1636
|
+
url: "/v1/ondo/swap/quote",
|
|
1637
|
+
queryParams: {
|
|
1638
|
+
symbol: params.symbol,
|
|
1639
|
+
side: params.side,
|
|
1640
|
+
duration: params.duration,
|
|
1641
|
+
...sizeParam(params)
|
|
1642
|
+
},
|
|
1643
|
+
attributes: Attributes.protected()
|
|
1644
|
+
});
|
|
1645
|
+
return OndoQuote.fromDto(dto);
|
|
1646
|
+
}
|
|
1647
|
+
async function buildOndoSwapTransaction(api, params) {
|
|
1648
|
+
const dto = await api.send({
|
|
1649
|
+
method: "POST",
|
|
1650
|
+
url: "/v1/ondo/swap/transaction",
|
|
1651
|
+
body: {
|
|
1652
|
+
symbol: params.symbol,
|
|
1653
|
+
chain: params.chain,
|
|
1654
|
+
wallet_address: params.walletAddress,
|
|
1655
|
+
amount: params.amount.raw.toString()
|
|
1656
|
+
},
|
|
1657
|
+
attributes: Attributes.protected()
|
|
1658
|
+
});
|
|
1659
|
+
assertFundingScaleAgrees(dto, params);
|
|
1660
|
+
return OndoSwapTransaction.fromDto(dto);
|
|
1661
|
+
}
|
|
1662
|
+
function assertFundingScaleAgrees(dto, params) {
|
|
1663
|
+
if (dto.pay_input_decimals !== params.amount.decimals) {
|
|
1664
|
+
throw new ValidationError(
|
|
1665
|
+
`pay_input_decimals: the swap was priced in ${dto.pay_input_decimals} decimals but the order was sized in ${params.amount.decimals}`
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
function sizeParam(params) {
|
|
1670
|
+
const tokenAmount = "tokenAmount" in params ? params.tokenAmount : void 0;
|
|
1671
|
+
const notionalValue = "notionalValue" in params ? params.notionalValue : void 0;
|
|
1672
|
+
if (tokenAmount !== void 0) {
|
|
1673
|
+
if (notionalValue !== void 0) {
|
|
1674
|
+
throw new ValidationError(
|
|
1675
|
+
"An Ondo quote takes tokenAmount or notionalValue, not both"
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
return { token_amount: formatRawAmount(tokenAmount) };
|
|
1679
|
+
}
|
|
1680
|
+
if (notionalValue === void 0) {
|
|
1681
|
+
throw new ValidationError(
|
|
1682
|
+
"An Ondo quote must be sized by tokenAmount or notionalValue"
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
return { notional_value: notionalValue };
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
// src/shared/core/checkout/ondo/ondo-namespace.ts
|
|
1689
|
+
var OndoNamespaceImpl = class {
|
|
1690
|
+
constructor(ctx) {
|
|
1691
|
+
this.ctx = ctx;
|
|
1692
|
+
this.log = internalLogger(ctx.logger, "ONDO");
|
|
1693
|
+
}
|
|
1694
|
+
async getTradingStatus(params) {
|
|
1695
|
+
return this.log.wrap("getTradingStatus", params, async () => {
|
|
1696
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1697
|
+
return getOndoTradingStatus(this.ctx.api, params);
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
async getQuote(params) {
|
|
1701
|
+
return this.log.wrap("getQuote", params, async () => {
|
|
1702
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1703
|
+
return getOndoQuote(this.ctx.api, params);
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
async buildSwapTransaction(params) {
|
|
1707
|
+
return this.log.wrap("buildSwapTransaction", params, async () => {
|
|
1708
|
+
await this.ctx.ensureUserAuthenticated();
|
|
1709
|
+
return buildOndoSwapTransaction(this.ctx.api, params);
|
|
1710
|
+
});
|
|
1711
|
+
}
|
|
1712
|
+
};
|
|
278
1713
|
|
|
279
|
-
// src/shared/core/blockchain/
|
|
1714
|
+
// src/shared/core/checkout/superstate/blockchain/abi.ts
|
|
280
1715
|
var SUPERSTATE_SWAP_ABI = [
|
|
281
1716
|
{
|
|
282
1717
|
type: "function",
|
|
@@ -487,272 +1922,36 @@ var SUPERSTATE_SWAP_ABI = [
|
|
|
487
1922
|
type: "error",
|
|
488
1923
|
name: "InvalidAmount",
|
|
489
1924
|
inputs: []
|
|
490
|
-
},
|
|
491
|
-
{
|
|
492
|
-
type: "error",
|
|
493
|
-
name: "SwapFailed",
|
|
494
|
-
inputs: [
|
|
495
|
-
{ name: "user", type: "address", internalType: "address" },
|
|
496
|
-
{ name: "token", type: "address", internalType: "address" }
|
|
497
|
-
]
|
|
498
|
-
}
|
|
499
|
-
];
|
|
500
|
-
|
|
501
|
-
// src/shared/types/blockchain/core.ts
|
|
502
|
-
var EvmWalletAddress = (value) => value;
|
|
503
|
-
var EvmContractAddress = (value) => value;
|
|
504
|
-
var HexEncodedTransactionData = (value) => value;
|
|
505
|
-
var AssetDecimals = (value) => value;
|
|
506
|
-
var MAX_UINT_256 = 2n ** 256n - 1n;
|
|
507
|
-
var assertUint256 = (value) => {
|
|
508
|
-
if (value < 0n || value > MAX_UINT_256) {
|
|
509
|
-
throw new Error(`Value out of uint256 bounds: ${value}`);
|
|
510
|
-
}
|
|
511
|
-
return value;
|
|
512
|
-
};
|
|
513
|
-
var BlockchainAmount = Object.assign(
|
|
514
|
-
(value) => value,
|
|
515
|
-
{
|
|
516
|
-
add: (a, b) => combineAmounts(a, b, (x, y) => x + y),
|
|
517
|
-
sub: (a, b) => combineAmounts(a, b, (x, y) => x - y)
|
|
518
|
-
}
|
|
519
|
-
);
|
|
520
|
-
function combineAmounts(a, b, op) {
|
|
521
|
-
if (a.decimals !== b.decimals) {
|
|
522
|
-
throw new Error(
|
|
523
|
-
`Cannot combine BlockchainAmounts with different decimals: ${a.decimals} vs ${b.decimals}`
|
|
524
|
-
);
|
|
525
|
-
}
|
|
526
|
-
const raw = op(a.raw, b.raw);
|
|
527
|
-
if (raw < 0n || raw > MAX_UINT_256) {
|
|
528
|
-
throw new Error(`BlockchainAmount out of uint256 bounds: ${raw}`);
|
|
529
|
-
}
|
|
530
|
-
return BlockchainAmount({ raw, decimals: a.decimals });
|
|
531
|
-
}
|
|
532
|
-
var AssetSymbol = (value) => value;
|
|
533
|
-
var StablecoinSymbol = (value) => value;
|
|
534
|
-
var KnownAssetSymbol = StablecoinSymbol;
|
|
535
|
-
var Bps = (value) => value;
|
|
536
|
-
|
|
537
|
-
// src/shared/core/blockchain/bps.ts
|
|
538
|
-
var BPS_DENOM = Bps(10000n);
|
|
539
|
-
function applyBps(amount, bps) {
|
|
540
|
-
return assertUint256(amount * bps / BPS_DENOM);
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
// src/shared/types/blockchain/ui.ts
|
|
544
|
-
var FormattedAmountUi = (value) => value;
|
|
545
|
-
var FormattedPercentUi = (value) => value;
|
|
546
|
-
var TxExplorerUrl = (value) => value;
|
|
547
|
-
var ShortenedWalletAddress = (value) => value;
|
|
548
|
-
var FormattedAmountAssetUi = (value) => value;
|
|
549
|
-
var AssetIconUrl = (value) => value;
|
|
550
|
-
|
|
551
|
-
// src/shared/core/blockchain/chain.ts
|
|
552
|
-
function getChainId(chain) {
|
|
553
|
-
switch (chain) {
|
|
554
|
-
case "ethereum_mainnet":
|
|
555
|
-
return 1;
|
|
556
|
-
case "ethereum_sepolia":
|
|
557
|
-
return 11155111;
|
|
558
|
-
default: {
|
|
559
|
-
const _exhaustive = chain;
|
|
560
|
-
return _exhaustive;
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
function getNetworkName(chain) {
|
|
565
|
-
switch (chain) {
|
|
566
|
-
case "ethereum_mainnet":
|
|
567
|
-
return "Ethereum";
|
|
568
|
-
case "ethereum_sepolia":
|
|
569
|
-
return "Ethereum Sepolia";
|
|
570
|
-
default: {
|
|
571
|
-
const _exhaustive = chain;
|
|
572
|
-
return _exhaustive;
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
function txExplorerUrl(chain, txHash) {
|
|
577
|
-
return TxExplorerUrl(`${explorerBaseUrl(chain)}/tx/${txHash}`);
|
|
578
|
-
}
|
|
579
|
-
function explorerBaseUrl(chain) {
|
|
580
|
-
switch (chain) {
|
|
581
|
-
case "ethereum_mainnet":
|
|
582
|
-
return "https://etherscan.io";
|
|
583
|
-
case "ethereum_sepolia":
|
|
584
|
-
return "https://sepolia.etherscan.io";
|
|
585
|
-
default: {
|
|
586
|
-
const _exhaustive = chain;
|
|
587
|
-
return _exhaustive;
|
|
588
|
-
}
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
// src/shared/core/blockchain/formatters.ts
|
|
593
|
-
var import_viem = require("viem");
|
|
594
|
-
|
|
595
|
-
// src/shared/core/blockchain/swap/math.ts
|
|
596
|
-
function computePrice({
|
|
597
|
-
inputTokenAmount,
|
|
598
|
-
outputTokenAmount
|
|
599
|
-
}) {
|
|
600
|
-
if (outputTokenAmount.raw === 0n) return null;
|
|
601
|
-
const scale = 10n ** BigInt(outputTokenAmount.decimals);
|
|
602
|
-
const raw = assertUint256(
|
|
603
|
-
inputTokenAmount.raw * scale / outputTokenAmount.raw
|
|
604
|
-
);
|
|
605
|
-
return BlockchainAmount({ raw, decimals: inputTokenAmount.decimals });
|
|
606
|
-
}
|
|
607
|
-
function computeSlip(amount, slippage) {
|
|
608
|
-
const retained = Bps(assertUint256(BPS_DENOM - slippage));
|
|
609
|
-
const slipRaw = applyBps(amount.raw, retained);
|
|
610
|
-
return BlockchainAmount({ raw: slipRaw, decimals: amount.decimals });
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// src/shared/core/blockchain/formatters.ts
|
|
614
|
-
function shortenAddress(address) {
|
|
615
|
-
const short = address.length > 10 ? `${address.slice(0, 6)}\u2026${address.slice(-4)}` : address;
|
|
616
|
-
return ShortenedWalletAddress(short);
|
|
617
|
-
}
|
|
618
|
-
function formatAmount(amount, locale, options) {
|
|
619
|
-
const decimal = formatRawAmount(amount);
|
|
620
|
-
let [integerPart, fractionPart = ""] = decimal.split(".");
|
|
621
|
-
const maxFractionDigits = options?.maxFractionDigits;
|
|
622
|
-
const minFractionDigits = maxFractionDigits !== void 0 ? Math.min(maxFractionDigits, amount.decimals) : Math.min(2, amount.decimals);
|
|
623
|
-
if (maxFractionDigits !== void 0 && fractionPart.length > maxFractionDigits) {
|
|
624
|
-
({ integerPart, fractionPart } = roundFractionHalfUp(
|
|
625
|
-
integerPart,
|
|
626
|
-
fractionPart,
|
|
627
|
-
maxFractionDigits
|
|
628
|
-
));
|
|
629
|
-
}
|
|
630
|
-
const fraction = minFractionDigits === 0 ? "" : fractionPart.padEnd(minFractionDigits, "0");
|
|
631
|
-
const integerFormatted = BigInt(integerPart).toLocaleString(locale);
|
|
632
|
-
if (minFractionDigits === 0 && fraction === "") {
|
|
633
|
-
return FormattedAmountUi(integerFormatted);
|
|
634
|
-
}
|
|
635
|
-
const decimalSeparator = new Intl.NumberFormat(locale).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
|
|
636
|
-
return FormattedAmountUi(`${integerFormatted}${decimalSeparator}${fraction}`);
|
|
637
|
-
}
|
|
638
|
-
function roundFractionHalfUp(integerPart, fractionPart, maxFractionDigits) {
|
|
639
|
-
if (fractionPart.length <= maxFractionDigits) {
|
|
640
|
-
return { integerPart, fractionPart };
|
|
641
|
-
}
|
|
642
|
-
if (maxFractionDigits === 0) {
|
|
643
|
-
const roundUp = fractionPart[0] >= "5";
|
|
644
|
-
const integer = BigInt(integerPart) + (roundUp ? 1n : 0n);
|
|
645
|
-
return { integerPart: integer.toString(), fractionPart: "" };
|
|
646
|
-
}
|
|
647
|
-
const trimmed = fractionPart.slice(0, maxFractionDigits);
|
|
648
|
-
if (fractionPart[maxFractionDigits] < "5") {
|
|
649
|
-
return { integerPart, fractionPart: trimmed };
|
|
650
|
-
}
|
|
651
|
-
const digits = trimmed.split("").map((digit) => Number.parseInt(digit, 10));
|
|
652
|
-
let carry = 1;
|
|
653
|
-
for (let i = digits.length - 1; i >= 0 && carry > 0; i -= 1) {
|
|
654
|
-
const sum = digits[i] + carry;
|
|
655
|
-
if (sum === 10) {
|
|
656
|
-
digits[i] = 0;
|
|
657
|
-
carry = 1;
|
|
658
|
-
} else {
|
|
659
|
-
digits[i] = sum;
|
|
660
|
-
carry = 0;
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
return {
|
|
664
|
-
integerPart: carry > 0 ? (BigInt(integerPart) + 1n).toString() : integerPart,
|
|
665
|
-
fractionPart: digits.join("")
|
|
666
|
-
};
|
|
667
|
-
}
|
|
668
|
-
function formatRawAmount(amount) {
|
|
669
|
-
return (0, import_viem.formatUnits)(amount.raw, amount.decimals);
|
|
670
|
-
}
|
|
671
|
-
function formatCompactAmount(amount, locale) {
|
|
672
|
-
const value = Number(formatRawAmount(amount));
|
|
673
|
-
const formatted = new Intl.NumberFormat(locale, {
|
|
674
|
-
notation: "compact",
|
|
675
|
-
maximumFractionDigits: 2
|
|
676
|
-
}).format(value);
|
|
677
|
-
return FormattedAmountUi(formatted);
|
|
678
|
-
}
|
|
679
|
-
function formatBpsAsPercent(bps, locale) {
|
|
680
|
-
const whole = bps / 100n;
|
|
681
|
-
const fraction = bps % 100n;
|
|
682
|
-
const wholeFormatted = whole.toLocaleString(locale);
|
|
683
|
-
const decimalSeparator = new Intl.NumberFormat(locale).formatToParts(1.1).find((p) => p.type === "decimal")?.value ?? ".";
|
|
684
|
-
if (fraction === 0n) {
|
|
685
|
-
return FormattedPercentUi(`${wholeFormatted}%`);
|
|
686
|
-
}
|
|
687
|
-
const fractionFormatted = fraction.toString().padStart(2, "0").replace(/0+$/, "");
|
|
688
|
-
return FormattedPercentUi(
|
|
689
|
-
`${wholeFormatted}${decimalSeparator}${fractionFormatted}%`
|
|
690
|
-
);
|
|
691
|
-
}
|
|
692
|
-
function usdAmount(amount) {
|
|
693
|
-
return FormattedAmountAssetUi(`$${amount}`);
|
|
694
|
-
}
|
|
695
|
-
function assetAmount(amount, symbol) {
|
|
696
|
-
return FormattedAmountAssetUi(`${amount} ${symbol}`);
|
|
697
|
-
}
|
|
698
|
-
var NA_AMOUNT_ASSET_UI = FormattedAmountAssetUi("-");
|
|
699
|
-
var USD_FRACTION_DIGITS = AssetDecimals(2);
|
|
700
|
-
function formattedUsdPrice(amount, locale) {
|
|
701
|
-
if (!amount) return NA_AMOUNT_ASSET_UI;
|
|
702
|
-
return usdAmount(
|
|
703
|
-
formatAmount(amount, locale, { maxFractionDigits: USD_FRACTION_DIGITS })
|
|
704
|
-
);
|
|
705
|
-
}
|
|
706
|
-
function formattedPricePerShare(quote, locale) {
|
|
707
|
-
if (!quote) return NA_AMOUNT_ASSET_UI;
|
|
708
|
-
return formattedUsdPrice(computePrice(quote), locale);
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
// src/shared/core/blockchain/math.ts
|
|
712
|
-
var import_viem2 = require("viem");
|
|
713
|
-
function parseBlockchainAmount(amount, decimals) {
|
|
714
|
-
const trimmed = amount.trim();
|
|
715
|
-
if (trimmed === "") return { valid: false, reason: { type: "empty" } };
|
|
716
|
-
if (trimmed.startsWith("-")) {
|
|
717
|
-
return { valid: false, reason: { type: "negative" } };
|
|
718
|
-
}
|
|
719
|
-
if (/[eE]/.test(trimmed)) {
|
|
720
|
-
return { valid: false, reason: { type: "invalid-format" } };
|
|
721
|
-
}
|
|
722
|
-
if (!/^\d+(\.\d+)?$/.test(trimmed)) {
|
|
723
|
-
return { valid: false, reason: { type: "invalid-format" } };
|
|
724
|
-
}
|
|
725
|
-
const [, fraction = ""] = trimmed.split(".");
|
|
726
|
-
if (fraction.length > decimals) {
|
|
727
|
-
return {
|
|
728
|
-
valid: false,
|
|
729
|
-
reason: { type: "too-many-decimals", maxDecimals: decimals }
|
|
730
|
-
};
|
|
731
|
-
}
|
|
732
|
-
try {
|
|
733
|
-
return {
|
|
734
|
-
valid: true,
|
|
735
|
-
amount: BlockchainAmount({
|
|
736
|
-
raw: (0, import_viem2.parseUnits)(trimmed, decimals),
|
|
737
|
-
decimals
|
|
738
|
-
})
|
|
739
|
-
};
|
|
740
|
-
} catch {
|
|
741
|
-
return { valid: false, reason: { type: "invalid-format" } };
|
|
1925
|
+
},
|
|
1926
|
+
{
|
|
1927
|
+
type: "error",
|
|
1928
|
+
name: "SwapFailed",
|
|
1929
|
+
inputs: [
|
|
1930
|
+
{ name: "user", type: "address", internalType: "address" },
|
|
1931
|
+
{ name: "token", type: "address", internalType: "address" }
|
|
1932
|
+
]
|
|
742
1933
|
}
|
|
743
|
-
|
|
1934
|
+
];
|
|
744
1935
|
|
|
745
|
-
// src/shared/core/blockchain/
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
(
|
|
751
|
-
);
|
|
752
|
-
|
|
753
|
-
|
|
1936
|
+
// src/shared/core/checkout/superstate/blockchain/math.ts
|
|
1937
|
+
function computePrice({
|
|
1938
|
+
inputTokenAmount,
|
|
1939
|
+
outputTokenAmount
|
|
1940
|
+
}) {
|
|
1941
|
+
if (outputTokenAmount.raw === 0n) return null;
|
|
1942
|
+
const scale = 10n ** BigInt(outputTokenAmount.decimals);
|
|
1943
|
+
const raw = assertUint256(
|
|
1944
|
+
inputTokenAmount.raw * scale / outputTokenAmount.raw
|
|
1945
|
+
);
|
|
1946
|
+
return BlockchainAmount({ raw, decimals: inputTokenAmount.decimals });
|
|
1947
|
+
}
|
|
1948
|
+
function computeSlip(amount, slippage) {
|
|
1949
|
+
const retained = Bps(assertUint256(BPS_DENOM - slippage));
|
|
1950
|
+
const slipRaw = applyBps(amount.raw, retained);
|
|
1951
|
+
return BlockchainAmount({ raw: slipRaw, decimals: amount.decimals });
|
|
1952
|
+
}
|
|
754
1953
|
|
|
755
|
-
// src/shared/core/blockchain/
|
|
1954
|
+
// src/shared/core/checkout/superstate/blockchain/quote.ts
|
|
756
1955
|
var SwapQuote = {
|
|
757
1956
|
/**
|
|
758
1957
|
* Assembles a {@link SwapQuote} from a raw contract {@link SwapPreview}. The
|
|
@@ -772,12 +1971,12 @@ var SwapQuote = {
|
|
|
772
1971
|
})
|
|
773
1972
|
};
|
|
774
1973
|
|
|
775
|
-
// src/shared/core/blockchain/
|
|
1974
|
+
// src/shared/core/checkout/superstate/blockchain/status.ts
|
|
776
1975
|
function isStopped(status) {
|
|
777
1976
|
return (status.stopped & status.swapLevel) !== 0n;
|
|
778
1977
|
}
|
|
779
1978
|
|
|
780
|
-
// src/shared/core/blockchain/
|
|
1979
|
+
// src/shared/core/checkout/superstate/blockchain/swapped-event.ts
|
|
781
1980
|
var import_viem3 = require("viem");
|
|
782
1981
|
function decodeSwappedOutputAmount(receipt, outputDecimals) {
|
|
783
1982
|
try {
|
|
@@ -795,420 +1994,658 @@ function decodeSwappedOutputAmount(receipt, outputDecimals) {
|
|
|
795
1994
|
}
|
|
796
1995
|
}
|
|
797
1996
|
|
|
798
|
-
// src/shared/core/
|
|
799
|
-
var
|
|
800
|
-
var
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
var
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
};
|
|
811
|
-
var USDC_ADDRESSES = {
|
|
812
|
-
ethereum_mainnet: EvmContractAddress(
|
|
813
|
-
"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
|
|
814
|
-
),
|
|
815
|
-
ethereum_sepolia: EvmContractAddress(
|
|
816
|
-
"0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238"
|
|
817
|
-
)
|
|
818
|
-
};
|
|
819
|
-
var USDT_ADDRESSES = {
|
|
820
|
-
ethereum_mainnet: EvmContractAddress(
|
|
821
|
-
"0xdac17f958d2ee523a2206206994597c13d831ec7"
|
|
822
|
-
),
|
|
823
|
-
ethereum_sepolia: EvmContractAddress(
|
|
824
|
-
"0x7169D38820dfd117C3FA1f22a697dBA58d90BA06"
|
|
825
|
-
)
|
|
826
|
-
};
|
|
827
|
-
var TOKEN_REGISTRY = {
|
|
828
|
-
erc20: (symbol) => {
|
|
829
|
-
switch (symbol) {
|
|
830
|
-
case "USDC":
|
|
831
|
-
return USDC;
|
|
832
|
-
case "USDT":
|
|
833
|
-
return USDT;
|
|
834
|
-
default:
|
|
835
|
-
throw new Error(`Unknown asset symbol: ${symbol}`);
|
|
836
|
-
}
|
|
837
|
-
},
|
|
838
|
-
contractAddress: (symbol, chain) => {
|
|
839
|
-
switch (symbol) {
|
|
840
|
-
case "USDC":
|
|
841
|
-
return USDC_ADDRESSES[chain];
|
|
842
|
-
case "USDT":
|
|
843
|
-
return USDT_ADDRESSES[chain];
|
|
844
|
-
default:
|
|
845
|
-
throw new Error(`Unknown asset symbol: ${symbol}`);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
1997
|
+
// src/shared/core/checkout/superstate/constants.ts
|
|
1998
|
+
var SUPERSTATE_ISSUER_NAME = "Superstate";
|
|
1999
|
+
var SUPERSTATE_SUPPORTED_INPUT_ASSETS = [USDC_SYMBOL];
|
|
2000
|
+
var SWAP_POLL_INTERVAL_MS = 15e3;
|
|
2001
|
+
var DEFAULT_AMOUNT_TO_COMPUTE_PRICE = 1000000n;
|
|
2002
|
+
var SLIPPAGE_OPTIONS_BPS = [25n, 50n, 100n, 200n, 500n].map(
|
|
2003
|
+
(n) => Bps(n)
|
|
2004
|
+
);
|
|
2005
|
+
var DEFAULT_SLIPPAGE_BPS = Bps(50n);
|
|
2006
|
+
var SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA = EvmContractAddress("0x84f8e9a6C9Cc12fe911259372EfCa5582C4ae557");
|
|
2007
|
+
var SUPERSTATE_SWAP_CONTRACT_ADDRESSES = {
|
|
2008
|
+
ethereum_sepolia: SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA
|
|
848
2009
|
};
|
|
2010
|
+
function superstateSwapContractAddress(chain) {
|
|
2011
|
+
return SUPERSTATE_SWAP_CONTRACT_ADDRESSES[chain] ?? null;
|
|
2012
|
+
}
|
|
849
2013
|
|
|
850
|
-
// src/shared/
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
});
|
|
856
|
-
var concatAll = (...items) => {
|
|
857
|
-
let result = empty;
|
|
858
|
-
for (const item of items) {
|
|
859
|
-
result = concat(result, item);
|
|
860
|
-
}
|
|
861
|
-
return result;
|
|
862
|
-
};
|
|
863
|
-
var protectedRequest = () => ({ protected: true });
|
|
864
|
-
var userAgent = () => ({ userAgent: true });
|
|
865
|
-
var idempotencyKey = () => ({
|
|
866
|
-
idempotencyKey: true
|
|
867
|
-
});
|
|
868
|
-
var clientCredentials = (credentials) => ({
|
|
869
|
-
clientCredentials: credentials
|
|
870
|
-
});
|
|
871
|
-
var retryAttempt = (attempt) => ({
|
|
872
|
-
retryAttempt: attempt
|
|
873
|
-
});
|
|
874
|
-
var renewAttempted = (value) => ({
|
|
875
|
-
renewAttempted: value
|
|
876
|
-
});
|
|
877
|
-
var isProtected = (attrs) => attrs?.protected === true;
|
|
878
|
-
var needUserAgent = (attrs) => attrs?.userAgent === true;
|
|
879
|
-
var isIdempotent = (attrs) => attrs?.idempotencyKey === true;
|
|
880
|
-
var getRetryAttempt = (attrs) => attrs?.retryAttempt ?? 0;
|
|
881
|
-
var wasRenewAttempted = (attrs) => attrs?.renewAttempted === true;
|
|
882
|
-
var getClientCredentials = (attrs) => attrs?.clientCredentials;
|
|
883
|
-
var Attributes = {
|
|
884
|
-
empty,
|
|
885
|
-
concat,
|
|
886
|
-
concatAll,
|
|
887
|
-
protected: protectedRequest,
|
|
888
|
-
isProtected,
|
|
889
|
-
userAgent,
|
|
890
|
-
needUserAgent,
|
|
891
|
-
idempotencyKey,
|
|
892
|
-
isIdempotent,
|
|
893
|
-
retryAttempt,
|
|
894
|
-
getRetryAttempt,
|
|
895
|
-
renewAttempted,
|
|
896
|
-
wasRenewAttempted,
|
|
897
|
-
clientCredentials,
|
|
898
|
-
getClientCredentials
|
|
899
|
-
};
|
|
2014
|
+
// src/shared/core/checkout/superstate/formatters.ts
|
|
2015
|
+
function formattedPricePerShare(quote, locale) {
|
|
2016
|
+
if (!quote) return NA_AMOUNT_ASSET_UI;
|
|
2017
|
+
return formattedUsdPrice(computePrice(quote), locale);
|
|
2018
|
+
}
|
|
900
2019
|
|
|
901
|
-
// src/shared/
|
|
902
|
-
var
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
};
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
to: EvmContractAddress(dto.to),
|
|
937
|
-
data: HexEncodedTransactionData(dto.data)
|
|
938
|
-
};
|
|
939
|
-
case "none":
|
|
940
|
-
return {
|
|
941
|
-
action: "none",
|
|
942
|
-
alreadyAllowed: dto.already_allowed
|
|
943
|
-
};
|
|
944
|
-
default: {
|
|
945
|
-
const _exhaustive = dto;
|
|
946
|
-
return _exhaustive;
|
|
947
|
-
}
|
|
948
|
-
}
|
|
2020
|
+
// src/shared/core/checkout/superstate/swap-namespace.ts
|
|
2021
|
+
var SuperstateSwapNamespaceImpl = class {
|
|
2022
|
+
constructor(ctx) {
|
|
2023
|
+
this.ctx = ctx;
|
|
2024
|
+
this.log = internalLogger(ctx.logger, "SUPERSTATE");
|
|
2025
|
+
}
|
|
2026
|
+
async getAuthorization(params) {
|
|
2027
|
+
return this.log.wrap("getAuthorization", params, async () => {
|
|
2028
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2029
|
+
return getSwapAuthorization(this.ctx.api, params);
|
|
2030
|
+
});
|
|
2031
|
+
}
|
|
2032
|
+
async getPreview(params) {
|
|
2033
|
+
return this.log.wrap("getPreview", params, async () => {
|
|
2034
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2035
|
+
return getSwapPreview(this.ctx.api, params);
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2038
|
+
async getStatus(params) {
|
|
2039
|
+
return this.log.wrap("getStatus", params, async () => {
|
|
2040
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2041
|
+
return getSwapStatus(this.ctx.api, params);
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
async getOutputToken(params) {
|
|
2045
|
+
return this.log.wrap("getOutputToken", params, async () => {
|
|
2046
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2047
|
+
return getSwapOutputToken(this.ctx.api, params);
|
|
2048
|
+
});
|
|
2049
|
+
}
|
|
2050
|
+
async allowWallet(params) {
|
|
2051
|
+
return this.log.wrap("allowWallet", params, async () => {
|
|
2052
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2053
|
+
return allowWallet(this.ctx.api, params);
|
|
2054
|
+
});
|
|
949
2055
|
}
|
|
950
2056
|
};
|
|
951
2057
|
|
|
952
|
-
// src/shared/api/frontline/
|
|
953
|
-
async function
|
|
954
|
-
|
|
955
|
-
method: "GET",
|
|
956
|
-
url: "/v1/wallet/authorized",
|
|
957
|
-
queryParams: {
|
|
958
|
-
chain: params.chain,
|
|
959
|
-
contract_address: params.contractAddress,
|
|
960
|
-
wallet_address: params.walletAddress
|
|
961
|
-
},
|
|
962
|
-
attributes: Attributes.protected()
|
|
963
|
-
});
|
|
964
|
-
return SwapAuthorization.fromDto(dto);
|
|
965
|
-
}
|
|
966
|
-
async function getSwapOutputToken(api, params) {
|
|
967
|
-
const dto = await api.send({
|
|
968
|
-
method: "GET",
|
|
969
|
-
url: "/v1/swap/output-token",
|
|
970
|
-
queryParams: {
|
|
971
|
-
chain: params.chain,
|
|
972
|
-
contract_address: params.contractAddress
|
|
973
|
-
},
|
|
974
|
-
attributes: Attributes.protected()
|
|
975
|
-
});
|
|
976
|
-
return toErc20Asset(dto);
|
|
977
|
-
}
|
|
978
|
-
async function getSwapPreview(api, params) {
|
|
979
|
-
const dto = await api.send({
|
|
980
|
-
method: "GET",
|
|
981
|
-
url: "/v1/swap/preview",
|
|
982
|
-
queryParams: {
|
|
983
|
-
chain: params.chain,
|
|
984
|
-
contract_address: params.contractAddress,
|
|
985
|
-
input_token: params.inputToken,
|
|
986
|
-
amount: params.amount.toString()
|
|
987
|
-
},
|
|
988
|
-
attributes: Attributes.protected()
|
|
989
|
-
});
|
|
990
|
-
return SwapPreview.fromDto(dto);
|
|
2058
|
+
// src/shared/api/frontline/offers.ts
|
|
2059
|
+
async function fetchOffers(api, clientCreds) {
|
|
2060
|
+
return fetchAllPages((params) => fetchOffersPage(api, params, clientCreds));
|
|
991
2061
|
}
|
|
992
|
-
async function
|
|
993
|
-
const
|
|
2062
|
+
async function fetchOffersPage(api, params, clientCreds) {
|
|
2063
|
+
const queryParams = PaginationParams.toQueryParams(params);
|
|
2064
|
+
const pageDto = await api.send({
|
|
994
2065
|
method: "GET",
|
|
995
|
-
url: "/v1/
|
|
996
|
-
queryParams
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
2066
|
+
url: "/v1/offers",
|
|
2067
|
+
queryParams,
|
|
2068
|
+
attributes: Attributes.concat(
|
|
2069
|
+
Attributes.protected(),
|
|
2070
|
+
Attributes.clientCredentials(clientCreds)
|
|
2071
|
+
)
|
|
1001
2072
|
});
|
|
1002
|
-
return
|
|
2073
|
+
return PaginatedResponse.fromDto(pageDto, Offer.fromDto);
|
|
1003
2074
|
}
|
|
1004
|
-
async function
|
|
2075
|
+
async function fetchOfferDetails(api, id, clientCreds) {
|
|
1005
2076
|
const dto = await api.send({
|
|
1006
2077
|
method: "GET",
|
|
1007
|
-
url:
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
spender: params.spender
|
|
1013
|
-
},
|
|
1014
|
-
attributes: Attributes.protected()
|
|
2078
|
+
url: `/v1/offers/${id}`,
|
|
2079
|
+
attributes: Attributes.concat(
|
|
2080
|
+
Attributes.protected(),
|
|
2081
|
+
Attributes.clientCredentials(clientCreds)
|
|
2082
|
+
)
|
|
1015
2083
|
});
|
|
1016
|
-
return
|
|
2084
|
+
return OfferDetail.fromDto(dto);
|
|
1017
2085
|
}
|
|
1018
|
-
|
|
2086
|
+
|
|
2087
|
+
// src/shared/core/offers/offers-namespace.ts
|
|
2088
|
+
var OffersNamespaceImpl = class {
|
|
2089
|
+
constructor(ctx) {
|
|
2090
|
+
this.ctx = ctx;
|
|
2091
|
+
this.log = internalLogger(ctx.logger, "OFFERS");
|
|
2092
|
+
}
|
|
2093
|
+
async list() {
|
|
2094
|
+
return this.log.wrap("list", void 0, async () => {
|
|
2095
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2096
|
+
return fetchOffers(this.ctx.api, void 0);
|
|
2097
|
+
});
|
|
2098
|
+
}
|
|
2099
|
+
async listPage(params) {
|
|
2100
|
+
return this.log.wrap("listPage", params, async () => {
|
|
2101
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2102
|
+
return fetchOffersPage(this.ctx.api, params, void 0);
|
|
2103
|
+
});
|
|
2104
|
+
}
|
|
2105
|
+
async get(id) {
|
|
2106
|
+
return this.log.wrap("get", id, async () => {
|
|
2107
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2108
|
+
return fetchOfferDetails(this.ctx.api, id, void 0);
|
|
2109
|
+
});
|
|
2110
|
+
}
|
|
2111
|
+
};
|
|
2112
|
+
|
|
2113
|
+
// src/shared/types/document-submission.ts
|
|
2114
|
+
var DocumentSubmission = {
|
|
2115
|
+
fromDto: (dto) => ({
|
|
2116
|
+
status: dto.status,
|
|
2117
|
+
formType: dto.form_type
|
|
2118
|
+
})
|
|
2119
|
+
};
|
|
2120
|
+
|
|
2121
|
+
// src/shared/api/frontline/documents.ts
|
|
2122
|
+
async function submitDocument(api, documentType, fields) {
|
|
1019
2123
|
const dto = await api.send({
|
|
1020
|
-
method: "
|
|
1021
|
-
url:
|
|
1022
|
-
|
|
1023
|
-
chain: params.chain,
|
|
1024
|
-
token_address: params.tokenAddress,
|
|
1025
|
-
owner: params.owner
|
|
1026
|
-
},
|
|
2124
|
+
method: "POST",
|
|
2125
|
+
url: `/v1/documents/${documentType}/submission`,
|
|
2126
|
+
body: fields,
|
|
1027
2127
|
attributes: Attributes.protected()
|
|
1028
2128
|
});
|
|
1029
|
-
return
|
|
2129
|
+
return DocumentSubmission.fromDto(dto);
|
|
1030
2130
|
}
|
|
1031
|
-
|
|
2131
|
+
|
|
2132
|
+
// src/shared/types/kyc.ts
|
|
2133
|
+
var KycToken = {
|
|
2134
|
+
fromDto: (dto) => ({
|
|
2135
|
+
token: dto.token
|
|
2136
|
+
})
|
|
2137
|
+
};
|
|
2138
|
+
|
|
2139
|
+
// src/shared/api/frontline/kyc.ts
|
|
2140
|
+
async function createKycToken(api, levelName, reset) {
|
|
1032
2141
|
const dto = await api.send({
|
|
1033
2142
|
method: "POST",
|
|
1034
|
-
url:
|
|
2143
|
+
url: "/v1/kyc-token",
|
|
1035
2144
|
body: {
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
signature: params.signature
|
|
2145
|
+
...levelName === void 0 ? {} : { level_name: levelName },
|
|
2146
|
+
...reset === void 0 ? {} : { reset }
|
|
1039
2147
|
},
|
|
1040
2148
|
attributes: Attributes.protected()
|
|
1041
2149
|
});
|
|
1042
|
-
return
|
|
1043
|
-
}
|
|
1044
|
-
function toErc20Asset(dto) {
|
|
1045
|
-
return {
|
|
1046
|
-
name: dto.name,
|
|
1047
|
-
symbol: AssetSymbol(dto.symbol),
|
|
1048
|
-
decimals: AssetDecimals(dto.decimals)
|
|
1049
|
-
};
|
|
2150
|
+
return KycToken.fromDto(dto);
|
|
1050
2151
|
}
|
|
1051
2152
|
|
|
1052
|
-
// src/shared/
|
|
1053
|
-
var
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
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
|
-
}
|
|
2153
|
+
// src/shared/types/pii.ts
|
|
2154
|
+
var Iso2CountryCode = (value) => value;
|
|
2155
|
+
var PiiJurisdiction = {
|
|
2156
|
+
fromDto: (dto) => ({
|
|
2157
|
+
iso2: Iso2CountryCode(dto.iso_2),
|
|
2158
|
+
name: dto.name
|
|
2159
|
+
})
|
|
1065
2160
|
};
|
|
1066
|
-
|
|
1067
|
-
// src/shared/types/asset.ts
|
|
1068
|
-
var AssetId = (value) => value;
|
|
1069
|
-
var AssetCode = (value) => value;
|
|
1070
|
-
var Asset = {
|
|
2161
|
+
var PiiAddress = {
|
|
1071
2162
|
fromDto: (dto) => ({
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
2163
|
+
street: dto.street,
|
|
2164
|
+
city: dto.city,
|
|
2165
|
+
state: dto.state,
|
|
2166
|
+
postalCode: dto.postal_code,
|
|
2167
|
+
country: dto.country
|
|
2168
|
+
})
|
|
2169
|
+
};
|
|
2170
|
+
var Pii = {
|
|
2171
|
+
fromDto: (dto) => ({
|
|
2172
|
+
kind: dto.kind,
|
|
2173
|
+
fullLegalName: dto.full_legal_name,
|
|
2174
|
+
dateOfBirth: dto.date_of_birth,
|
|
2175
|
+
jurisdiction: dto.jurisdiction ? PiiJurisdiction.fromDto(dto.jurisdiction) : null,
|
|
2176
|
+
taxId: dto.tax_id,
|
|
2177
|
+
permanentAddress: PiiAddress.fromDto(dto.permanent_address)
|
|
1076
2178
|
})
|
|
1077
2179
|
};
|
|
1078
2180
|
|
|
1079
|
-
// src/shared/
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
2181
|
+
// src/shared/api/frontline/pii.ts
|
|
2182
|
+
async function fetchPii(api) {
|
|
2183
|
+
const dto = await api.send({
|
|
2184
|
+
method: "GET",
|
|
2185
|
+
url: "/v1/pii",
|
|
2186
|
+
attributes: Attributes.protected()
|
|
2187
|
+
});
|
|
2188
|
+
return Pii.fromDto(dto);
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
// src/shared/types/requirement.ts
|
|
2192
|
+
var RequirementId = (value) => value;
|
|
2193
|
+
var Requirement = {
|
|
1083
2194
|
fromDto: (dto) => ({
|
|
1084
|
-
id:
|
|
1085
|
-
slug: OfferSlug(dto.slug),
|
|
2195
|
+
id: RequirementId(dto.id),
|
|
1086
2196
|
type: dto.type,
|
|
1087
|
-
|
|
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
|
|
2197
|
+
details: dto.details
|
|
1092
2198
|
})
|
|
1093
2199
|
};
|
|
2200
|
+
var RequirementStatusInfo = {
|
|
2201
|
+
fromStatusesDto: (dto) => Object.entries(dto.statuses).map(
|
|
2202
|
+
([id, value]) => typeof value === "string" ? { id: RequirementId(id), status: value, action: null } : {
|
|
2203
|
+
id: RequirementId(id),
|
|
2204
|
+
status: value.status,
|
|
2205
|
+
action: value.action ?? null,
|
|
2206
|
+
kycLevel: value.kyc_level,
|
|
2207
|
+
kycReset: value.kyc_reset
|
|
2208
|
+
}
|
|
2209
|
+
)
|
|
2210
|
+
};
|
|
1094
2211
|
|
|
1095
|
-
// src/shared/
|
|
1096
|
-
async function
|
|
1097
|
-
const
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
2212
|
+
// src/shared/api/frontline/requirements.ts
|
|
2213
|
+
async function fetchOfferRequirements(api, offerId, clientCreds) {
|
|
2214
|
+
const response = await api.send({
|
|
2215
|
+
method: "GET",
|
|
2216
|
+
url: `/v1/offers/${offerId}/requirements`,
|
|
2217
|
+
attributes: Attributes.concat(
|
|
2218
|
+
Attributes.protected(),
|
|
2219
|
+
Attributes.clientCredentials(clientCreds)
|
|
2220
|
+
)
|
|
2221
|
+
});
|
|
2222
|
+
return Object.fromEntries(
|
|
2223
|
+
Object.entries(response.options).map(([optionId, list]) => [
|
|
2224
|
+
optionId,
|
|
2225
|
+
list.data.map(Requirement.fromDto)
|
|
2226
|
+
])
|
|
1101
2227
|
);
|
|
1102
|
-
return crypto.subtle.digest("SHA-256", buffer);
|
|
1103
2228
|
}
|
|
1104
|
-
function
|
|
1105
|
-
const
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
2229
|
+
async function fetchRequirementStatuses(api, offerId) {
|
|
2230
|
+
const response = await api.send({
|
|
2231
|
+
method: "GET",
|
|
2232
|
+
url: `/v1/offers/${offerId}/requirements/statuses`,
|
|
2233
|
+
attributes: Attributes.protected()
|
|
2234
|
+
});
|
|
2235
|
+
return RequirementStatusInfo.fromStatusesDto(response);
|
|
2236
|
+
}
|
|
2237
|
+
|
|
2238
|
+
// src/shared/core/requirements/requirements-namespace.ts
|
|
2239
|
+
var RequirementsNamespaceImpl = class {
|
|
2240
|
+
constructor(ctx) {
|
|
2241
|
+
this.ctx = ctx;
|
|
2242
|
+
this.log = internalLogger(ctx.logger, "REQUIREMENTS");
|
|
1109
2243
|
}
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
2244
|
+
async forOffer(offerId) {
|
|
2245
|
+
return this.log.wrap("forOffer", offerId, async () => {
|
|
2246
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2247
|
+
return fetchOfferRequirements(
|
|
2248
|
+
this.ctx.api,
|
|
2249
|
+
offerId,
|
|
2250
|
+
void 0
|
|
2251
|
+
);
|
|
2252
|
+
});
|
|
1114
2253
|
}
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
const buffer = bytes.buffer;
|
|
1121
|
-
return arrayBufferToBase64Url(buffer, false);
|
|
1122
|
-
}
|
|
1123
|
-
function notBlankStringOrNull(value) {
|
|
1124
|
-
if (value?.trim()) {
|
|
1125
|
-
return value;
|
|
1126
|
-
} else {
|
|
1127
|
-
return null;
|
|
2254
|
+
async statuses(offerId) {
|
|
2255
|
+
return this.log.wrap("statuses", offerId, async () => {
|
|
2256
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2257
|
+
return fetchRequirementStatuses(this.ctx.api, offerId);
|
|
2258
|
+
});
|
|
1128
2259
|
}
|
|
1129
|
-
|
|
2260
|
+
async createKycToken(params) {
|
|
2261
|
+
return this.log.wrap("createKycToken", params, async () => {
|
|
2262
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2263
|
+
return createKycToken(
|
|
2264
|
+
this.ctx.api,
|
|
2265
|
+
params?.levelName,
|
|
2266
|
+
params?.reset
|
|
2267
|
+
);
|
|
2268
|
+
});
|
|
2269
|
+
}
|
|
2270
|
+
async getPii() {
|
|
2271
|
+
return this.log.wrap("getPii", void 0, async () => {
|
|
2272
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2273
|
+
return fetchPii(this.ctx.api);
|
|
2274
|
+
});
|
|
2275
|
+
}
|
|
2276
|
+
async submitDocument(params) {
|
|
2277
|
+
return this.log.wrap("submitDocument", params, async () => {
|
|
2278
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2279
|
+
return submitDocument(
|
|
2280
|
+
this.ctx.api,
|
|
2281
|
+
params.documentType,
|
|
2282
|
+
params.fields
|
|
2283
|
+
);
|
|
2284
|
+
});
|
|
2285
|
+
}
|
|
2286
|
+
};
|
|
1130
2287
|
|
|
1131
|
-
// src/shared/
|
|
1132
|
-
var
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
2288
|
+
// src/shared/api/nabu/tokens.ts
|
|
2289
|
+
var import_viem4 = require("viem");
|
|
2290
|
+
|
|
2291
|
+
// src/shared/api/frontline/config.ts
|
|
2292
|
+
var HEADER_API_VERSION = "X-API-Version";
|
|
2293
|
+
|
|
2294
|
+
// src/shared/api/http-client.ts
|
|
2295
|
+
var HttpClient = class {
|
|
2296
|
+
constructor(config, middleware = {}, logger = null, options = {}) {
|
|
2297
|
+
this.config = config;
|
|
2298
|
+
this.middleware = middleware;
|
|
2299
|
+
this.log = internalLogger(logger, "HTTP");
|
|
2300
|
+
this.makeRequestId = options.makeRequestId ?? defaultMakeRequestId;
|
|
2301
|
+
}
|
|
2302
|
+
async send(request) {
|
|
2303
|
+
return this.runRequestWithAfterMiddleware(request);
|
|
2304
|
+
}
|
|
2305
|
+
/**
|
|
2306
|
+
* Runs beforeRequest, executeRequest, then the full afterRequest middleware
|
|
2307
|
+
* chain. Used by send() and by the retry() callback so that when a
|
|
2308
|
+
* middleware calls retry(), the retried response also goes through all
|
|
2309
|
+
* afterRequest middleware (e.g. session renewal, retry). Middleware
|
|
2310
|
+
* must use request.attributes.retryAttempt (or similar) to avoid infinite
|
|
2311
|
+
* recursion when they trigger retries.
|
|
2312
|
+
*/
|
|
2313
|
+
async runRequestWithAfterMiddleware(request) {
|
|
2314
|
+
const preparedRequest = await this.runBeforeRequestMiddleware(
|
|
2315
|
+
this.withClientDefaults(request)
|
|
2316
|
+
);
|
|
2317
|
+
let response = await this.executeRequest(preparedRequest);
|
|
2318
|
+
for (const middleware of this.middleware.afterRequest ?? []) {
|
|
2319
|
+
response = await middleware({
|
|
2320
|
+
request: preparedRequest,
|
|
2321
|
+
response,
|
|
2322
|
+
retry: (nextRequest = preparedRequest) => this.runRequestWithAfterMiddleware(nextRequest)
|
|
2323
|
+
});
|
|
1144
2324
|
}
|
|
1145
|
-
|
|
1146
|
-
|
|
2325
|
+
return response;
|
|
2326
|
+
}
|
|
2327
|
+
withClientDefaults(request) {
|
|
2328
|
+
const url = this.resolveUrl(request.url);
|
|
2329
|
+
const headers = {
|
|
2330
|
+
...request.headers ?? {},
|
|
2331
|
+
...this.config.xApiVersion !== void 0 ? { [HEADER_API_VERSION]: this.config.xApiVersion } : {}
|
|
2332
|
+
};
|
|
2333
|
+
return {
|
|
2334
|
+
...request,
|
|
2335
|
+
url,
|
|
2336
|
+
headers,
|
|
2337
|
+
// Only when absent: a retry or a post-renewal re-send arrives with the
|
|
2338
|
+
// first attempt's id already on it, and keeping it is the whole point.
|
|
2339
|
+
attributes: Attributes.getRequestId(request.attributes) === null ? Attributes.concat(
|
|
2340
|
+
request.attributes ?? Attributes.empty,
|
|
2341
|
+
Attributes.requestId(this.makeRequestId())
|
|
2342
|
+
) : request.attributes
|
|
2343
|
+
};
|
|
2344
|
+
}
|
|
2345
|
+
/**
|
|
2346
|
+
* Resolves a request URL against the client's baseUrl.
|
|
2347
|
+
*
|
|
2348
|
+
* @internal Public only for testing. Do not use in application code; use
|
|
2349
|
+
* {@link HttpClient.send} with a path and the client will resolve the URL.
|
|
2350
|
+
*/
|
|
2351
|
+
resolveUrl(url) {
|
|
2352
|
+
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
2353
|
+
return url;
|
|
1147
2354
|
}
|
|
1148
|
-
|
|
1149
|
-
|
|
2355
|
+
const base = this.config.baseUrl.replace(/\/$/, "");
|
|
2356
|
+
const path = url.startsWith("/") ? url : `/${url}`;
|
|
2357
|
+
return base + path;
|
|
2358
|
+
}
|
|
2359
|
+
async runBeforeRequestMiddleware(initialRequest) {
|
|
2360
|
+
let request = initialRequest;
|
|
2361
|
+
for (const middleware of this.middleware.beforeRequest ?? []) {
|
|
2362
|
+
request = await middleware(request);
|
|
1150
2363
|
}
|
|
1151
|
-
|
|
1152
|
-
|
|
2364
|
+
return request;
|
|
2365
|
+
}
|
|
2366
|
+
/**
|
|
2367
|
+
* One physical attempt, logged as one line.
|
|
2368
|
+
*
|
|
2369
|
+
* A non-2xx is a `warn` rather than an `error` because the wire does not
|
|
2370
|
+
* know whether it is a failure: the retry middleware may turn a 503 into a
|
|
2371
|
+
* success, and the token registry reads a 404 as "not listed". The namespace
|
|
2372
|
+
* above decides, and logs the `error` when it does.
|
|
2373
|
+
*/
|
|
2374
|
+
async executeRequest(request) {
|
|
2375
|
+
const requestId2 = Attributes.getRequestId(request.attributes);
|
|
2376
|
+
const log = requestId2 === null ? this.log : this.log.child({ requestId: requestId2 });
|
|
2377
|
+
const attempt = Attributes.getRetryAttempt(request.attributes) + 1;
|
|
2378
|
+
const startedAt = Date.now();
|
|
2379
|
+
log.debug(() => ({
|
|
2380
|
+
msg: "request sent",
|
|
2381
|
+
fields: describeRequestUnredacted(request)
|
|
2382
|
+
}));
|
|
2383
|
+
try {
|
|
2384
|
+
const response = await makeRequest(request);
|
|
2385
|
+
const elapsed = Date.now() - startedAt;
|
|
2386
|
+
const outcome = () => ({
|
|
2387
|
+
msg: "request completed",
|
|
2388
|
+
fields: {
|
|
2389
|
+
...identifyRequest(request),
|
|
2390
|
+
"http.response.status_code": response.status,
|
|
2391
|
+
duration_ms: elapsed,
|
|
2392
|
+
attempt
|
|
2393
|
+
}
|
|
2394
|
+
});
|
|
2395
|
+
if (response.status >= 200 && response.status < 300) {
|
|
2396
|
+
log.info(outcome);
|
|
2397
|
+
} else {
|
|
2398
|
+
log.warn(outcome);
|
|
2399
|
+
}
|
|
2400
|
+
log.debug(() => ({
|
|
2401
|
+
msg: "response received",
|
|
2402
|
+
fields: { body: response.body }
|
|
2403
|
+
}));
|
|
2404
|
+
return requestId2 === null ? response : { ...response, requestId: requestId2 };
|
|
2405
|
+
} catch (error) {
|
|
2406
|
+
const elapsed = Date.now() - startedAt;
|
|
2407
|
+
log.warning(
|
|
2408
|
+
() => ({
|
|
2409
|
+
msg: "request threw",
|
|
2410
|
+
fields: {
|
|
2411
|
+
...identifyRequest(request),
|
|
2412
|
+
duration_ms: elapsed,
|
|
2413
|
+
attempt
|
|
2414
|
+
}
|
|
2415
|
+
}),
|
|
2416
|
+
error
|
|
2417
|
+
);
|
|
2418
|
+
throw error;
|
|
1153
2419
|
}
|
|
1154
|
-
return {
|
|
1155
|
-
id: OfferId(dto.id),
|
|
1156
|
-
slug: OfferSlug(dto.slug),
|
|
1157
|
-
type: dto.type,
|
|
1158
|
-
name: dto.name,
|
|
1159
|
-
asset: Asset.fromDto(dto.asset),
|
|
1160
|
-
fundingAssets: dto.funding_assets.map(Asset.fromDto),
|
|
1161
|
-
about: notBlankStringOrNull(dto.about),
|
|
1162
|
-
tagline: dto.tagline,
|
|
1163
|
-
bannerUrl: dto.banner_url,
|
|
1164
|
-
logoUrl: dto.logo_url,
|
|
1165
|
-
category: dto.category,
|
|
1166
|
-
startsAt: new Date(dto.starts_at),
|
|
1167
|
-
endsAt: dto.ends_at ? new Date(dto.ends_at) : null,
|
|
1168
|
-
faqs: dto.faqs.map(FaqItem.fromDto),
|
|
1169
|
-
links: dto.links.map(Link.fromDto),
|
|
1170
|
-
milestones: dto.milestones.map(Milestone.fromDto),
|
|
1171
|
-
options: dto.options.map(OfferOption.fromDto),
|
|
1172
|
-
terms: dto.terms.map(TermItem.fromDto)
|
|
1173
|
-
};
|
|
1174
2420
|
}
|
|
1175
2421
|
};
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
};
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
2422
|
+
function identifyRequest(request) {
|
|
2423
|
+
const { host, path } = splitUrl(request.url);
|
|
2424
|
+
return {
|
|
2425
|
+
"http.request.method": request.method,
|
|
2426
|
+
"server.address": host,
|
|
2427
|
+
"url.path": path
|
|
2428
|
+
};
|
|
2429
|
+
}
|
|
2430
|
+
function splitUrl(url) {
|
|
2431
|
+
try {
|
|
2432
|
+
const parsed = new URL(url);
|
|
2433
|
+
return { host: parsed.host, path: parsed.pathname };
|
|
2434
|
+
} catch (_) {
|
|
2435
|
+
return { host: null, path: url };
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
function defaultMakeRequestId() {
|
|
2439
|
+
return Math.random().toString(36).slice(2, 10).padEnd(8, "0");
|
|
2440
|
+
}
|
|
2441
|
+
function describeRequestUnredacted(request) {
|
|
2442
|
+
return {
|
|
2443
|
+
"http.request.method": request.method,
|
|
2444
|
+
"url.full": buildUrlWithQueryParams(request.url, request.queryParams),
|
|
2445
|
+
headers: request.headers,
|
|
2446
|
+
...request.method === "POST" ? { body: request.body } : {}
|
|
2447
|
+
};
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
// src/shared/types/token-metadata.ts
|
|
2451
|
+
var TokenLogoUrl = (value) => value;
|
|
2452
|
+
var TokenLogo = {
|
|
2453
|
+
/** `baseUrl` is the registry origin; registry URLs are root-relative. */
|
|
2454
|
+
fromDto: (dto, baseUrl) => dto.kind === "VECTOR" ? { kind: "VECTOR", url: resolveLogoUrl(dto.url, baseUrl) } : {
|
|
2455
|
+
kind: "RASTER",
|
|
2456
|
+
original: logoImageFromDto(dto.original, baseUrl),
|
|
2457
|
+
variants: dto.variants.map((v) => logoImageFromDto(v, baseUrl))
|
|
2458
|
+
}
|
|
1199
2459
|
};
|
|
1200
|
-
var
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
2460
|
+
var TokenMetadata = {
|
|
2461
|
+
/** `baseUrl` is the registry origin; registry logo URLs are root-relative. */
|
|
2462
|
+
fromDto: (dto, baseUrl) => {
|
|
2463
|
+
assertSupportedSchemaVersion(dto.schema_version);
|
|
2464
|
+
return {
|
|
2465
|
+
identifier: {
|
|
2466
|
+
chain: EthereumChain(dto.chain),
|
|
2467
|
+
address: EvmContractAddress(dto.address)
|
|
2468
|
+
},
|
|
2469
|
+
name: dto.name,
|
|
2470
|
+
symbol: AssetSymbol(dto.symbol),
|
|
2471
|
+
decimals: AssetDecimals(dto.decimals),
|
|
2472
|
+
logo: TokenLogo.fromDto(dto.logo, baseUrl),
|
|
2473
|
+
logoDark: dto.logo_dark === void 0 ? null : TokenLogo.fromDto(dto.logo_dark, baseUrl)
|
|
2474
|
+
};
|
|
2475
|
+
},
|
|
2476
|
+
/**
|
|
2477
|
+
* Maps the complete registry snapshot to every token it lists across the
|
|
2478
|
+
* chains this SDK models, skipping native coins and chains outside
|
|
2479
|
+
* {@link EthereumChain} (e.g. Solana) rather than failing on them — the
|
|
2480
|
+
* registry may serve chains ahead of the SDK's type surface.
|
|
2481
|
+
*/
|
|
2482
|
+
fromRegistryDto: (dto, baseUrl) => {
|
|
2483
|
+
assertSupportedSchemaVersion(dto.schema_version);
|
|
2484
|
+
return dto.chains.flatMap((chainDto) => {
|
|
2485
|
+
let chain;
|
|
2486
|
+
try {
|
|
2487
|
+
chain = EthereumChain(chainDto.chain);
|
|
2488
|
+
} catch {
|
|
2489
|
+
return [];
|
|
2490
|
+
}
|
|
2491
|
+
return tokensOfChain(chain, chainDto.assets, baseUrl);
|
|
2492
|
+
});
|
|
2493
|
+
},
|
|
2494
|
+
/**
|
|
2495
|
+
* Maps a chain snapshot to the tokens it lists, skipping the chain's native
|
|
2496
|
+
* coin (`kind: 'COIN'`, no contract address).
|
|
2497
|
+
*/
|
|
2498
|
+
fromChainAssetsDto: (dto, baseUrl) => {
|
|
2499
|
+
assertSupportedSchemaVersion(dto.schema_version);
|
|
2500
|
+
return tokensOfChain(EthereumChain(dto.chain), dto.assets, baseUrl);
|
|
2501
|
+
}
|
|
1205
2502
|
};
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
2503
|
+
function tokensOfChain(chain, assets, baseUrl) {
|
|
2504
|
+
return assets.filter((asset) => asset.kind === "TOKEN" && asset.address !== void 0).map((asset) => ({
|
|
2505
|
+
identifier: {
|
|
2506
|
+
chain,
|
|
2507
|
+
// The filter above cannot narrow `address` for the type checker.
|
|
2508
|
+
address: EvmContractAddress(asset.address)
|
|
2509
|
+
},
|
|
2510
|
+
name: asset.name,
|
|
2511
|
+
symbol: AssetSymbol(asset.symbol),
|
|
2512
|
+
decimals: AssetDecimals(asset.decimals),
|
|
2513
|
+
logo: TokenLogo.fromDto(asset.logo, baseUrl),
|
|
2514
|
+
logoDark: asset.logo_dark === void 0 ? null : TokenLogo.fromDto(asset.logo_dark, baseUrl)
|
|
2515
|
+
}));
|
|
2516
|
+
}
|
|
2517
|
+
function assertSupportedSchemaVersion(version) {
|
|
2518
|
+
if (version !== 1) {
|
|
2519
|
+
throw new ValidationError(
|
|
2520
|
+
`Unsupported token registry schema_version: ${version}`
|
|
2521
|
+
);
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
var logoImageFromDto = (dto, baseUrl) => ({
|
|
2525
|
+
url: resolveLogoUrl(dto.url, baseUrl),
|
|
2526
|
+
width: dto.width,
|
|
2527
|
+
height: dto.height
|
|
2528
|
+
});
|
|
2529
|
+
var resolveLogoUrl = (url, baseUrl) => TokenLogoUrl(
|
|
2530
|
+
url.startsWith("http") ? url : `${baseUrl.replace(/\/$/, "")}${url}`
|
|
2531
|
+
);
|
|
2532
|
+
|
|
2533
|
+
// src/shared/api/nabu/tokens.ts
|
|
2534
|
+
function createNabuApiClient(baseUrl, logger = null) {
|
|
2535
|
+
return new HttpClient({ baseUrl }, {}, logger);
|
|
2536
|
+
}
|
|
2537
|
+
async function fetchTokenMetadata(client, token) {
|
|
2538
|
+
const address = checksummed(token.address);
|
|
2539
|
+
let response;
|
|
2540
|
+
try {
|
|
2541
|
+
response = await client.send({
|
|
2542
|
+
method: "GET",
|
|
2543
|
+
url: `/${token.chain}/token/${address}`
|
|
2544
|
+
});
|
|
2545
|
+
} catch (error) {
|
|
2546
|
+
if (isRegistryHtmlFallback(error)) {
|
|
2547
|
+
return null;
|
|
2548
|
+
}
|
|
2549
|
+
throw error;
|
|
2550
|
+
}
|
|
2551
|
+
if (response.status === 404) {
|
|
2552
|
+
return null;
|
|
2553
|
+
}
|
|
2554
|
+
assertOk(response);
|
|
2555
|
+
if (response.body === null) {
|
|
2556
|
+
throw new ValidationError(
|
|
2557
|
+
`Token registry returned an empty body for token "${address}" on "${token.chain}"`
|
|
2558
|
+
);
|
|
2559
|
+
}
|
|
2560
|
+
return TokenMetadata.fromDto(response.body, client.config.baseUrl);
|
|
2561
|
+
}
|
|
2562
|
+
async function fetchTokensMetadata(client, chain) {
|
|
2563
|
+
let response;
|
|
2564
|
+
try {
|
|
2565
|
+
response = await client.send({
|
|
2566
|
+
method: "GET",
|
|
2567
|
+
url: `/${chain}/assets.json`
|
|
2568
|
+
});
|
|
2569
|
+
} catch (error) {
|
|
2570
|
+
if (isRegistryHtmlFallback(error)) {
|
|
2571
|
+
throw new ValidationError(
|
|
2572
|
+
`Token registry returned non-JSON for the "${chain}" snapshot`
|
|
2573
|
+
);
|
|
2574
|
+
}
|
|
2575
|
+
throw error;
|
|
2576
|
+
}
|
|
2577
|
+
assertOk(response);
|
|
2578
|
+
if (response.body === null) {
|
|
2579
|
+
throw new ValidationError(
|
|
2580
|
+
`Token registry returned an empty "${chain}" snapshot`
|
|
2581
|
+
);
|
|
2582
|
+
}
|
|
2583
|
+
return TokenMetadata.fromChainAssetsDto(response.body, client.config.baseUrl);
|
|
2584
|
+
}
|
|
2585
|
+
async function fetchAllTokensMetadata(client) {
|
|
2586
|
+
let response;
|
|
2587
|
+
try {
|
|
2588
|
+
response = await client.send({
|
|
2589
|
+
method: "GET",
|
|
2590
|
+
url: `/assets.json`
|
|
2591
|
+
});
|
|
2592
|
+
} catch (error) {
|
|
2593
|
+
if (isRegistryHtmlFallback(error)) {
|
|
2594
|
+
throw new ValidationError(
|
|
2595
|
+
"Token registry returned non-JSON for the complete snapshot"
|
|
2596
|
+
);
|
|
2597
|
+
}
|
|
2598
|
+
throw error;
|
|
2599
|
+
}
|
|
2600
|
+
assertOk(response);
|
|
2601
|
+
if (response.body === null) {
|
|
2602
|
+
throw new ValidationError(
|
|
2603
|
+
"Token registry returned an empty complete snapshot"
|
|
2604
|
+
);
|
|
2605
|
+
}
|
|
2606
|
+
return TokenMetadata.fromRegistryDto(response.body, client.config.baseUrl);
|
|
2607
|
+
}
|
|
2608
|
+
function isRegistryHtmlFallback(error) {
|
|
2609
|
+
return error instanceof HttpError && error.response.status >= 200 && error.response.status < 300;
|
|
2610
|
+
}
|
|
2611
|
+
function assertOk(response) {
|
|
2612
|
+
if (response.status < 200 || response.status >= 300) {
|
|
2613
|
+
throw new HttpError(response);
|
|
2614
|
+
}
|
|
2615
|
+
}
|
|
2616
|
+
function checksummed(address) {
|
|
2617
|
+
try {
|
|
2618
|
+
return (0, import_viem4.getAddress)(address);
|
|
2619
|
+
} catch (_) {
|
|
2620
|
+
throw new ValidationError(`Invalid EVM contract address: "${address}"`);
|
|
2621
|
+
}
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2624
|
+
// src/shared/core/tokens/tokens-namespace.ts
|
|
2625
|
+
var TokensNamespaceImpl = class {
|
|
2626
|
+
/**
|
|
2627
|
+
* Takes the registry origin rather than a `SharedNamespaceContext`: the
|
|
2628
|
+
* registry is unauthenticated and on its own host, so the frontline sender
|
|
2629
|
+
* and the auth check would both be dead weight here.
|
|
2630
|
+
*/
|
|
2631
|
+
constructor(baseUrl, logger = null) {
|
|
2632
|
+
this.api = createNabuApiClient(baseUrl, logger);
|
|
2633
|
+
this.log = internalLogger(logger, "TOKENS");
|
|
2634
|
+
}
|
|
2635
|
+
get(token) {
|
|
2636
|
+
return this.log.wrap(
|
|
2637
|
+
"get",
|
|
2638
|
+
token,
|
|
2639
|
+
() => fetchTokenMetadata(this.api, token)
|
|
2640
|
+
);
|
|
2641
|
+
}
|
|
2642
|
+
list(chain) {
|
|
2643
|
+
return this.log.wrap(
|
|
2644
|
+
"list",
|
|
2645
|
+
chain,
|
|
2646
|
+
() => chain === void 0 ? fetchAllTokensMetadata(this.api) : fetchTokensMetadata(this.api, chain)
|
|
2647
|
+
);
|
|
2648
|
+
}
|
|
1212
2649
|
};
|
|
1213
2650
|
|
|
1214
2651
|
// src/shared/types/offer-option-address.ts
|
|
@@ -1282,195 +2719,79 @@ async function createWalletOwnershipChallenge(api, params) {
|
|
|
1282
2719
|
});
|
|
1283
2720
|
return WalletOwnershipChallenge.fromDto(dto);
|
|
1284
2721
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
}
|
|
1291
|
-
async getAuthorization(params) {
|
|
1292
|
-
await this.ctx.ensureUserAuthenticated();
|
|
1293
|
-
return getSwapAuthorization(this.ctx.api, params);
|
|
1294
|
-
}
|
|
1295
|
-
async getPreview(params) {
|
|
1296
|
-
await this.ctx.ensureUserAuthenticated();
|
|
1297
|
-
return getSwapPreview(this.ctx.api, params);
|
|
1298
|
-
}
|
|
1299
|
-
async getStatus(params) {
|
|
1300
|
-
await this.ctx.ensureUserAuthenticated();
|
|
1301
|
-
return getSwapStatus(this.ctx.api, params);
|
|
1302
|
-
}
|
|
1303
|
-
async getOutputToken(params) {
|
|
1304
|
-
await this.ctx.ensureUserAuthenticated();
|
|
1305
|
-
return getSwapOutputToken(this.ctx.api, params);
|
|
1306
|
-
}
|
|
1307
|
-
async requestWalletOwnershipChallenge(params) {
|
|
1308
|
-
await this.ctx.ensureUserAuthenticated();
|
|
1309
|
-
return createWalletOwnershipChallenge(this.ctx.api, params);
|
|
1310
|
-
}
|
|
1311
|
-
async allowWallet(params) {
|
|
1312
|
-
await this.ctx.ensureUserAuthenticated();
|
|
1313
|
-
return allowWallet(this.ctx.api, params);
|
|
1314
|
-
}
|
|
1315
|
-
};
|
|
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),
|
|
2722
|
+
async function connectExternalWallet(api, params) {
|
|
2723
|
+
const dto = await api.send({
|
|
2724
|
+
method: "POST",
|
|
2725
|
+
url: `/v1/offers/${params.offerId}/addresses`,
|
|
2726
|
+
body: ConnectExternalWalletParams.toDto(params),
|
|
1376
2727
|
attributes: Attributes.protected()
|
|
1377
2728
|
});
|
|
1378
|
-
return
|
|
2729
|
+
return OfferOptionAddress.fromDto(dto);
|
|
1379
2730
|
}
|
|
1380
|
-
async function
|
|
1381
|
-
const
|
|
2731
|
+
async function listOptionAddresses(api, offerId, offerOptionId) {
|
|
2732
|
+
const { data } = await api.send({
|
|
1382
2733
|
method: "GET",
|
|
1383
|
-
url: `/v1/
|
|
2734
|
+
url: `/v1/offers/${offerId}/addresses`,
|
|
2735
|
+
queryParams: { offer_option_id: offerOptionId },
|
|
1384
2736
|
attributes: Attributes.protected()
|
|
1385
2737
|
});
|
|
1386
|
-
return
|
|
2738
|
+
return data.map(OfferOptionAddress.fromDto);
|
|
1387
2739
|
}
|
|
1388
|
-
async function
|
|
2740
|
+
async function removeOptionAddress(api, offerId, addressId) {
|
|
1389
2741
|
const dto = await api.send({
|
|
1390
|
-
method: "
|
|
1391
|
-
url:
|
|
1392
|
-
body: CreateParticipationParams.toDto(params),
|
|
2742
|
+
method: "DELETE",
|
|
2743
|
+
url: `/v1/offers/${offerId}/addresses/${addressId}`,
|
|
1393
2744
|
attributes: Attributes.protected()
|
|
1394
2745
|
});
|
|
1395
|
-
return
|
|
2746
|
+
return OfferOptionAddress.fromDto(dto);
|
|
1396
2747
|
}
|
|
1397
2748
|
|
|
1398
|
-
// src/shared/core/
|
|
1399
|
-
var
|
|
2749
|
+
// src/shared/core/wallets/wallets-namespace.ts
|
|
2750
|
+
var WalletsNamespaceImpl = class {
|
|
1400
2751
|
constructor(ctx) {
|
|
1401
2752
|
this.ctx = ctx;
|
|
2753
|
+
this.log = internalLogger(ctx.logger, "WALLETS");
|
|
1402
2754
|
}
|
|
1403
|
-
async
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
async fetchParticipation(id) {
|
|
1412
|
-
await this.ctx.ensureUserAuthenticated();
|
|
1413
|
-
return fetchParticipation(this.ctx.api, id);
|
|
2755
|
+
async createOwnershipChallenge(params) {
|
|
2756
|
+
return this.log.wrap("createOwnershipChallenge", params, async () => {
|
|
2757
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2758
|
+
return createWalletOwnershipChallenge(
|
|
2759
|
+
this.ctx.api,
|
|
2760
|
+
params
|
|
2761
|
+
);
|
|
2762
|
+
});
|
|
1414
2763
|
}
|
|
1415
|
-
async
|
|
1416
|
-
|
|
1417
|
-
|
|
2764
|
+
async connectExternal(params) {
|
|
2765
|
+
return this.log.wrap("connectExternal", params, async () => {
|
|
2766
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2767
|
+
return connectExternalWallet(this.ctx.api, params);
|
|
2768
|
+
});
|
|
1418
2769
|
}
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
var ClientSecret = (value) => value;
|
|
1429
|
-
|
|
1430
|
-
// src/shared/pkce.ts
|
|
1431
|
-
async function generatePKCEParams(config) {
|
|
1432
|
-
const state = generateSecureRandomBase64Url(32);
|
|
1433
|
-
const codeVerifier = generateSecureRandomBase64Url(32);
|
|
1434
|
-
const codeChallengeRaw = await sha256(codeVerifier);
|
|
1435
|
-
const codeChallenge = arrayBufferToBase64Url(codeChallengeRaw, false);
|
|
1436
|
-
return {
|
|
1437
|
-
clientId: config.clientId,
|
|
1438
|
-
responseType: "code",
|
|
1439
|
-
redirectUri: config.redirectUri,
|
|
1440
|
-
codeChallenge: CodeChallenge(codeChallenge),
|
|
1441
|
-
codeChallengeMethod: "S256",
|
|
1442
|
-
state: PKCEState(state),
|
|
1443
|
-
codeVerifier: CodeVerifier(codeVerifier)
|
|
1444
|
-
};
|
|
1445
|
-
}
|
|
1446
|
-
|
|
1447
|
-
// src/shared/types/document-submission.ts
|
|
1448
|
-
var DocumentSubmission = {
|
|
1449
|
-
fromDto: (dto) => ({
|
|
1450
|
-
status: dto.status,
|
|
1451
|
-
formType: dto.form_type
|
|
1452
|
-
})
|
|
1453
|
-
};
|
|
1454
|
-
|
|
1455
|
-
// src/shared/types/errors.ts
|
|
1456
|
-
var NotImplementedError = class extends Error {
|
|
1457
|
-
constructor(message = "Not implemented yet") {
|
|
1458
|
-
super(message);
|
|
1459
|
-
this.name = "NotImplementedError";
|
|
2770
|
+
async list(params) {
|
|
2771
|
+
return this.log.wrap("list", params, async () => {
|
|
2772
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2773
|
+
return listOptionAddresses(
|
|
2774
|
+
this.ctx.api,
|
|
2775
|
+
params.offerId,
|
|
2776
|
+
params.offerOptionId
|
|
2777
|
+
);
|
|
2778
|
+
});
|
|
1460
2779
|
}
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
2780
|
+
async remove(params) {
|
|
2781
|
+
return this.log.wrap("remove", params, async () => {
|
|
2782
|
+
await this.ctx.ensureUserAuthenticated();
|
|
2783
|
+
return removeOptionAddress(
|
|
2784
|
+
this.ctx.api,
|
|
2785
|
+
params.offerId,
|
|
2786
|
+
params.addressId
|
|
2787
|
+
);
|
|
2788
|
+
});
|
|
1466
2789
|
}
|
|
1467
2790
|
};
|
|
1468
2791
|
|
|
1469
|
-
// src/shared/types/
|
|
1470
|
-
var
|
|
1471
|
-
|
|
1472
|
-
token: dto.token
|
|
1473
|
-
})
|
|
2792
|
+
// src/shared/types/blockchain/wallet-error.ts
|
|
2793
|
+
var RedactedWalletError = {
|
|
2794
|
+
fromWalletError: (error) => error.type === "unknown" ? { type: "unknown" } : error
|
|
1474
2795
|
};
|
|
1475
2796
|
|
|
1476
2797
|
// src/shared/types/oauth-session.ts
|
|
@@ -1489,55 +2810,6 @@ var OAuthSession = {
|
|
|
1489
2810
|
}
|
|
1490
2811
|
};
|
|
1491
2812
|
|
|
1492
|
-
// src/shared/types/pii.ts
|
|
1493
|
-
var Iso2CountryCode = (value) => value;
|
|
1494
|
-
var PiiJurisdiction = {
|
|
1495
|
-
fromDto: (dto) => ({
|
|
1496
|
-
iso2: Iso2CountryCode(dto.iso_2),
|
|
1497
|
-
name: dto.name
|
|
1498
|
-
})
|
|
1499
|
-
};
|
|
1500
|
-
var PiiAddress = {
|
|
1501
|
-
fromDto: (dto) => ({
|
|
1502
|
-
street: dto.street,
|
|
1503
|
-
city: dto.city,
|
|
1504
|
-
state: dto.state,
|
|
1505
|
-
postalCode: dto.postal_code,
|
|
1506
|
-
country: dto.country
|
|
1507
|
-
})
|
|
1508
|
-
};
|
|
1509
|
-
var Pii = {
|
|
1510
|
-
fromDto: (dto) => ({
|
|
1511
|
-
kind: dto.kind,
|
|
1512
|
-
fullLegalName: dto.full_legal_name,
|
|
1513
|
-
dateOfBirth: dto.date_of_birth,
|
|
1514
|
-
jurisdiction: dto.jurisdiction ? PiiJurisdiction.fromDto(dto.jurisdiction) : null,
|
|
1515
|
-
taxId: dto.tax_id,
|
|
1516
|
-
permanentAddress: PiiAddress.fromDto(dto.permanent_address)
|
|
1517
|
-
})
|
|
1518
|
-
};
|
|
1519
|
-
|
|
1520
|
-
// src/shared/types/requirement.ts
|
|
1521
|
-
var RequirementId = (value) => value;
|
|
1522
|
-
var Requirement = {
|
|
1523
|
-
fromDto: (dto) => ({
|
|
1524
|
-
id: RequirementId(dto.id),
|
|
1525
|
-
type: dto.type,
|
|
1526
|
-
details: dto.details
|
|
1527
|
-
})
|
|
1528
|
-
};
|
|
1529
|
-
var RequirementStatusInfo = {
|
|
1530
|
-
fromStatusesDto: (dto) => Object.entries(dto.statuses).map(
|
|
1531
|
-
([id, value]) => typeof value === "string" ? { id: RequirementId(id), status: value, action: null } : {
|
|
1532
|
-
id: RequirementId(id),
|
|
1533
|
-
status: value.status,
|
|
1534
|
-
action: value.action ?? null,
|
|
1535
|
-
kycLevel: value.kyc_level,
|
|
1536
|
-
kycReset: value.kyc_reset
|
|
1537
|
-
}
|
|
1538
|
-
)
|
|
1539
|
-
};
|
|
1540
|
-
|
|
1541
2813
|
// src/shared/types/user.ts
|
|
1542
2814
|
var UserId = (value) => value;
|
|
1543
2815
|
var UserEmail = (value) => value;
|
|
@@ -1561,20 +2833,26 @@ var User = {
|
|
|
1561
2833
|
Blockchain,
|
|
1562
2834
|
BlockchainAmount,
|
|
1563
2835
|
Bps,
|
|
2836
|
+
Chain,
|
|
1564
2837
|
ClientCredentialsOAuth,
|
|
1565
2838
|
ClientId,
|
|
1566
2839
|
ClientSecret,
|
|
1567
2840
|
CodeChallenge,
|
|
1568
2841
|
CodeVerifier,
|
|
2842
|
+
CoinListTokenSaleNamespaceImpl,
|
|
1569
2843
|
ConnectExternalWalletParams,
|
|
1570
2844
|
CreateParticipationParams,
|
|
1571
2845
|
CreateWalletOwnershipChallengeParams,
|
|
1572
2846
|
Cursor,
|
|
1573
2847
|
DEFAULT_AMOUNT_TO_COMPUTE_PRICE,
|
|
2848
|
+
DEFAULT_ONDO_AMOUNT_TO_COMPUTE_PRICE,
|
|
1574
2849
|
DEFAULT_SLIPPAGE_BPS,
|
|
2850
|
+
DecimalString,
|
|
1575
2851
|
DocumentSubmission,
|
|
1576
2852
|
ERC20_ABI,
|
|
2853
|
+
ETHEREUM_CHAINS,
|
|
1577
2854
|
Erc20NamespaceImpl,
|
|
2855
|
+
EthereumChain,
|
|
1578
2856
|
EvmContractAddress,
|
|
1579
2857
|
EvmWalletAddress,
|
|
1580
2858
|
FaqItem,
|
|
@@ -1582,10 +2860,13 @@ var User = {
|
|
|
1582
2860
|
FormattedAmountUi,
|
|
1583
2861
|
FormattedPercentUi,
|
|
1584
2862
|
HexEncodedTransactionData,
|
|
2863
|
+
HttpError,
|
|
2864
|
+
InvariantError,
|
|
1585
2865
|
Iso2CountryCode,
|
|
1586
2866
|
KnownAssetSymbol,
|
|
1587
2867
|
KycToken,
|
|
1588
2868
|
Link,
|
|
2869
|
+
MAX_ASSET_DECIMALS,
|
|
1589
2870
|
MAX_UINT_256,
|
|
1590
2871
|
Milestone,
|
|
1591
2872
|
NA_AMOUNT_ASSET_UI,
|
|
@@ -1593,6 +2874,9 @@ var User = {
|
|
|
1593
2874
|
NotImplementedError,
|
|
1594
2875
|
OAuthRefreshToken,
|
|
1595
2876
|
OAuthSession,
|
|
2877
|
+
ONDO_POLL_INTERVAL_MS,
|
|
2878
|
+
ONDO_QUOTE_EXPIRY_THRESHOLD_MS,
|
|
2879
|
+
ONDO_SUPPORTED_INPUT_ASSETS,
|
|
1596
2880
|
Offer,
|
|
1597
2881
|
OfferDetail,
|
|
1598
2882
|
OfferId,
|
|
@@ -1602,6 +2886,12 @@ var User = {
|
|
|
1602
2886
|
OfferOptionId,
|
|
1603
2887
|
OfferOptionSlug,
|
|
1604
2888
|
OfferSlug,
|
|
2889
|
+
OfferToken,
|
|
2890
|
+
OffersNamespaceImpl,
|
|
2891
|
+
OndoNamespaceImpl,
|
|
2892
|
+
OndoQuote,
|
|
2893
|
+
OndoSwapTransaction,
|
|
2894
|
+
OndoTradingStatus,
|
|
1605
2895
|
PKCEState,
|
|
1606
2896
|
PaginatedResponse,
|
|
1607
2897
|
PaginationParams,
|
|
@@ -1611,27 +2901,37 @@ var User = {
|
|
|
1611
2901
|
Pii,
|
|
1612
2902
|
PiiAddress,
|
|
1613
2903
|
PiiJurisdiction,
|
|
2904
|
+
RedactedWalletError,
|
|
1614
2905
|
RedirectUri,
|
|
1615
2906
|
Requirement,
|
|
1616
2907
|
RequirementId,
|
|
1617
2908
|
RequirementStatusInfo,
|
|
2909
|
+
RequirementsNamespaceImpl,
|
|
1618
2910
|
SLIPPAGE_OPTIONS_BPS,
|
|
2911
|
+
SOLANA_CHAINS,
|
|
2912
|
+
STABLE_DECIMALS,
|
|
2913
|
+
SUPERSTATE_ISSUER_NAME,
|
|
2914
|
+
SUPERSTATE_SUPPORTED_INPUT_ASSETS,
|
|
1619
2915
|
SUPERSTATE_SWAP_ABI,
|
|
1620
2916
|
SUPERSTATE_SWAP_CONTRACT_ADDRESS_SEPOLIA,
|
|
1621
|
-
SUPERSTATE_TOS_URL,
|
|
1622
2917
|
SWAP_POLL_INTERVAL_MS,
|
|
1623
2918
|
ShortenedWalletAddress,
|
|
2919
|
+
SolanaChain,
|
|
1624
2920
|
StablecoinSymbol,
|
|
2921
|
+
SuperstateSwapNamespaceImpl,
|
|
1625
2922
|
SwapAuthorization,
|
|
1626
|
-
SwapNamespaceImpl,
|
|
1627
2923
|
SwapPreview,
|
|
1628
2924
|
SwapQuote,
|
|
1629
2925
|
SwapStatus,
|
|
1630
2926
|
TOKEN_REGISTRY,
|
|
1631
2927
|
TermItem,
|
|
2928
|
+
Ticker,
|
|
1632
2929
|
TokenAllowance,
|
|
1633
2930
|
TokenBalance,
|
|
1634
|
-
|
|
2931
|
+
TokenLogo,
|
|
2932
|
+
TokenLogoUrl,
|
|
2933
|
+
TokenMetadata,
|
|
2934
|
+
TokensNamespaceImpl,
|
|
1635
2935
|
TxExplorerUrl,
|
|
1636
2936
|
USDC,
|
|
1637
2937
|
USDC_SYMBOL,
|
|
@@ -1640,11 +2940,17 @@ var User = {
|
|
|
1640
2940
|
User,
|
|
1641
2941
|
UserEmail,
|
|
1642
2942
|
UserId,
|
|
2943
|
+
ValidationError,
|
|
1643
2944
|
WalletAddress,
|
|
1644
2945
|
WalletOwnershipChallenge,
|
|
2946
|
+
WalletsNamespaceImpl,
|
|
2947
|
+
apiErrorCode,
|
|
1645
2948
|
applyBps,
|
|
1646
2949
|
assertUint256,
|
|
1647
2950
|
assetAmount,
|
|
2951
|
+
blockchainAmountFromRawOrThrow,
|
|
2952
|
+
chainFromId,
|
|
2953
|
+
computeOndoPrice,
|
|
1648
2954
|
computePrice,
|
|
1649
2955
|
computeSlip,
|
|
1650
2956
|
decodeSwappedOutputAmount,
|
|
@@ -1659,8 +2965,11 @@ var User = {
|
|
|
1659
2965
|
getChainId,
|
|
1660
2966
|
getNetworkName,
|
|
1661
2967
|
isStopped,
|
|
2968
|
+
ondoSwapContractAddress,
|
|
1662
2969
|
parseBlockchainAmount,
|
|
2970
|
+
parseUint256,
|
|
1663
2971
|
shortenAddress,
|
|
2972
|
+
superstateSwapContractAddress,
|
|
1664
2973
|
txExplorerUrl,
|
|
1665
2974
|
usdAmount
|
|
1666
2975
|
});
|