@unifold/core 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,420 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ ExecutionStatus: () => ExecutionStatus,
24
+ SOLANA_USDC_ADDRESS: () => SOLANA_USDC_ADDRESS,
25
+ createDepositAddress: () => createDepositAddress,
26
+ createMeldSession: () => createMeldSession,
27
+ getApiBaseUrl: () => getApiBaseUrl,
28
+ getChainName: () => getChainName,
29
+ getFiatCurrencies: () => getFiatCurrencies,
30
+ getIconUrl: () => getIconUrl,
31
+ getIconUrlWithCdn: () => getIconUrlWithCdn,
32
+ getMeldQuotes: () => getMeldQuotes,
33
+ getPreferredIconUrl: () => getPreferredIconUrl,
34
+ getProjectConfig: () => getProjectConfig,
35
+ getSupportedDepositTokens: () => getSupportedDepositTokens,
36
+ getTokenChains: () => getTokenChains,
37
+ getWalletByChainType: () => getWalletByChainType,
38
+ i18n: () => i18n,
39
+ queryExecutions: () => queryExecutions,
40
+ setApiConfig: () => setApiConfig,
41
+ useUserIp: () => useUserIp
42
+ });
43
+ module.exports = __toCommonJS(index_exports);
44
+
45
+ // src/lib/api.ts
46
+ var API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL || "https://api.unifold.io";
47
+ var DEFAULT_PUBLISHABLE_KEY = "pk_test_123";
48
+ var DEFAULT_CONFIG = {};
49
+ function setApiConfig(config) {
50
+ if (config.publishableKey !== void 0) {
51
+ if (!config.publishableKey || config.publishableKey.trim() === "") {
52
+ throw new Error(
53
+ "Unifold SDK: publishableKey cannot be empty. Please provide a valid publishable key."
54
+ );
55
+ }
56
+ if (!config.publishableKey.startsWith("pk_test_") && !config.publishableKey.startsWith("pk_live_")) {
57
+ console.warn(
58
+ 'Unifold SDK: publishableKey should start with "pk_test_" or "pk_live_". Please ensure you are using a valid publishable key.'
59
+ );
60
+ }
61
+ DEFAULT_PUBLISHABLE_KEY = config.publishableKey;
62
+ }
63
+ if (config.baseUrl) {
64
+ API_BASE_URL = config.baseUrl;
65
+ }
66
+ if (config.defaultConfig) {
67
+ DEFAULT_CONFIG = config.defaultConfig;
68
+ }
69
+ }
70
+ function getApiBaseUrl() {
71
+ return API_BASE_URL;
72
+ }
73
+ function validatePublishableKey(key) {
74
+ if (!key || key.trim() === "") {
75
+ throw new Error(
76
+ "Unifold SDK: No publishable key configured. Please provide a valid publishable key via setApiConfig() or pass it directly to the API function."
77
+ );
78
+ }
79
+ if (key === "pk_test_123") {
80
+ console.warn(
81
+ 'Unifold SDK: Using default test key "pk_test_123". This should only be used for local development. Please use a real publishable key in production.'
82
+ );
83
+ }
84
+ }
85
+ function getIconUrl(iconPath) {
86
+ const normalizedPath = iconPath.startsWith("/") ? iconPath : `/${iconPath}`;
87
+ return `${API_BASE_URL}/api/public${normalizedPath}`;
88
+ }
89
+ function getIconUrlWithCdn(iconPath, assetCdnUrl) {
90
+ if (!assetCdnUrl) {
91
+ return getIconUrl(iconPath);
92
+ }
93
+ const normalizedPath = iconPath.startsWith("/") ? iconPath : `/${iconPath}`;
94
+ const baseUrl = assetCdnUrl.endsWith("/") ? assetCdnUrl.slice(0, -1) : assetCdnUrl;
95
+ return `${baseUrl}/api/public${normalizedPath}`;
96
+ }
97
+ async function createDepositAddress(overrides, publishableKey) {
98
+ if (!overrides?.external_user_id) {
99
+ throw new Error("external_user_id is required");
100
+ }
101
+ const payload = {
102
+ external_user_id: overrides.external_user_id,
103
+ destination_chain_type: overrides?.destination_chain_type || "ethereum",
104
+ destination_chain_id: overrides?.destination_chain_id || DEFAULT_CONFIG.destinationChainId || "8453",
105
+ destination_token_address: overrides?.destination_token_address || DEFAULT_CONFIG.destinationTokenAddress || "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
106
+ recipient_address: overrides?.recipient_address || DEFAULT_CONFIG.recipientAddress || "0x309a4154a2CD4153Da886E780890C9cb5161553C",
107
+ client_metadata: overrides?.client_metadata || {}
108
+ };
109
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
110
+ validatePublishableKey(pk);
111
+ const response = await fetch(`${API_BASE_URL}/v1/public/deposit_addresses`, {
112
+ method: "POST",
113
+ headers: {
114
+ accept: "application/json",
115
+ "x-publishable-key": pk,
116
+ "Content-Type": "application/json"
117
+ },
118
+ body: JSON.stringify(payload)
119
+ });
120
+ if (!response.ok) {
121
+ throw new Error(`Failed to create EOA: ${response.statusText}`);
122
+ }
123
+ return response.json();
124
+ }
125
+ function getWalletByChainType(wallets, chainType) {
126
+ return wallets.find((wallet) => wallet.chain_type === chainType);
127
+ }
128
+ var ExecutionStatus = /* @__PURE__ */ ((ExecutionStatus2) => {
129
+ ExecutionStatus2["DELAYED"] = "delayed";
130
+ ExecutionStatus2["FAILED"] = "failed";
131
+ ExecutionStatus2["PENDING"] = "pending";
132
+ ExecutionStatus2["REFUNDED"] = "refunded";
133
+ ExecutionStatus2["SUCCEEDED"] = "succeeded";
134
+ ExecutionStatus2["WAITING"] = "waiting";
135
+ return ExecutionStatus2;
136
+ })(ExecutionStatus || {});
137
+ var SOLANA_USDC_ADDRESS = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
138
+ async function queryExecutions(externalUserId, publishableKey) {
139
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
140
+ validatePublishableKey(pk);
141
+ const response = await fetch(
142
+ `${API_BASE_URL}/v1/public/direct_executions/query`,
143
+ {
144
+ method: "POST",
145
+ headers: {
146
+ accept: "application/json",
147
+ "x-publishable-key": pk,
148
+ "Content-Type": "application/json"
149
+ },
150
+ body: JSON.stringify({
151
+ external_user_id: externalUserId
152
+ })
153
+ }
154
+ );
155
+ if (!response.ok) {
156
+ throw new Error(`Failed to query executions: ${response.statusText}`);
157
+ }
158
+ return response.json();
159
+ }
160
+ async function getSupportedDepositTokens(publishableKey) {
161
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
162
+ validatePublishableKey(pk);
163
+ const response = await fetch(
164
+ `${API_BASE_URL}/v1/public/tokens/supported_deposit_tokens`,
165
+ {
166
+ method: "GET",
167
+ headers: {
168
+ accept: "application/json",
169
+ "x-publishable-key": pk
170
+ }
171
+ }
172
+ );
173
+ if (!response.ok) {
174
+ throw new Error(
175
+ `Failed to fetch supported deposit tokens: ${response.statusText}`
176
+ );
177
+ }
178
+ return response.json();
179
+ }
180
+ async function getMeldQuotes(request, publishableKey) {
181
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
182
+ validatePublishableKey(pk);
183
+ const response = await fetch(
184
+ `${API_BASE_URL}/v1/public/onramps/meld/quotes`,
185
+ {
186
+ method: "POST",
187
+ headers: {
188
+ accept: "application/json",
189
+ "x-publishable-key": pk,
190
+ "Content-Type": "application/json"
191
+ },
192
+ body: JSON.stringify(request)
193
+ }
194
+ );
195
+ if (!response.ok) {
196
+ throw new Error(`Failed to fetch Meld quotes: ${response.statusText}`);
197
+ }
198
+ return response.json();
199
+ }
200
+ async function createMeldSession(request, publishableKey) {
201
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
202
+ validatePublishableKey(pk);
203
+ const response = await fetch(
204
+ `${API_BASE_URL}/v1/public/onramps/meld/sessions`,
205
+ {
206
+ method: "POST",
207
+ headers: {
208
+ accept: "application/json",
209
+ "x-publishable-key": pk,
210
+ "Content-Type": "application/json"
211
+ },
212
+ body: JSON.stringify(request)
213
+ }
214
+ );
215
+ if (!response.ok) {
216
+ throw new Error(`Failed to create Meld session: ${response.statusText}`);
217
+ }
218
+ return response.json();
219
+ }
220
+ function getPreferredIconUrl(iconUrls, preferredFormat = "svg") {
221
+ if (!iconUrls || iconUrls.length === 0) {
222
+ return void 0;
223
+ }
224
+ const preferred = iconUrls.find((icon) => icon.format === preferredFormat);
225
+ if (preferred) {
226
+ return preferred.url;
227
+ }
228
+ return iconUrls[0]?.url;
229
+ }
230
+ async function getFiatCurrencies(publishableKey) {
231
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
232
+ validatePublishableKey(pk);
233
+ const response = await fetch(
234
+ `${API_BASE_URL}/v1/public/onramps/fiat_currencies`,
235
+ {
236
+ method: "GET",
237
+ headers: {
238
+ accept: "application/json",
239
+ "x-publishable-key": pk
240
+ }
241
+ }
242
+ );
243
+ if (!response.ok) {
244
+ throw new Error(`Failed to fetch fiat currencies: ${response.statusText}`);
245
+ }
246
+ return response.json();
247
+ }
248
+ async function getTokenChains() {
249
+ const response = await fetch(`${API_BASE_URL}/v1/public/tokens/chains`, {
250
+ method: "GET",
251
+ headers: {
252
+ accept: "application/json"
253
+ }
254
+ });
255
+ if (!response.ok) {
256
+ throw new Error(`Failed to fetch token chains: ${response.statusText}`);
257
+ }
258
+ return response.json();
259
+ }
260
+ function getChainName(chains, chainType, chainId) {
261
+ const byId = chains.find((c) => c.chain_id === chainId);
262
+ if (byId) return byId.chain_name;
263
+ const byType = chains.find((c) => c.chain_type === chainType);
264
+ if (byType) return byType.chain_name;
265
+ return chainType.charAt(0).toUpperCase() + chainType.slice(1);
266
+ }
267
+ async function getProjectConfig(publishableKey) {
268
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
269
+ validatePublishableKey(pk);
270
+ const response = await fetch(`${API_BASE_URL}/v1/public/projects/config`, {
271
+ method: "GET",
272
+ headers: {
273
+ accept: "application/json",
274
+ "x-publishable-key": pk
275
+ }
276
+ });
277
+ if (!response.ok) {
278
+ throw new Error(`Failed to fetch project config: ${response.statusText}`);
279
+ }
280
+ return response.json();
281
+ }
282
+
283
+ // src/hooks/use-user-ip.ts
284
+ var import_react_query = require("@tanstack/react-query");
285
+ async function getIpViaIpApi() {
286
+ const url = "https://ipapi.co/json";
287
+ const response = await fetch(url);
288
+ if (!response.ok) {
289
+ throw new Error(`ipapi.co failed: ${response.statusText}`);
290
+ }
291
+ const data = await response.json();
292
+ return {
293
+ alpha2: data.country_code.toLowerCase(),
294
+ state: data.region_code?.toLowerCase()
295
+ };
296
+ }
297
+ function useUserIp() {
298
+ const {
299
+ data: userIpInfo,
300
+ isLoading,
301
+ error
302
+ } = (0, import_react_query.useQuery)({
303
+ queryKey: ["getUserIpInfo"],
304
+ queryFn: async () => {
305
+ try {
306
+ const ipApiData = await getIpViaIpApi();
307
+ console.log("IP detected via ipapi.co:", ipApiData);
308
+ return ipApiData;
309
+ } catch (ipApiError) {
310
+ console.error("IP detection failed:", ipApiError);
311
+ throw ipApiError;
312
+ }
313
+ },
314
+ // Cache configuration to reduce API calls
315
+ refetchOnMount: false,
316
+ refetchOnReconnect: true,
317
+ refetchOnWindowFocus: false,
318
+ // Optional: Increase cache duration to 1 hour for even better rate limit protection
319
+ staleTime: 1e3 * 60 * 60,
320
+ // 1 hour - data considered fresh for 1 hour
321
+ gcTime: 1e3 * 60 * 60 * 24
322
+ // 24 hours - keep in cache for 24 hours
323
+ });
324
+ return {
325
+ userIpInfo,
326
+ isLoading,
327
+ error
328
+ };
329
+ }
330
+
331
+ // src/lib/i18n/en.json
332
+ var en_default = {
333
+ transferCrypto: {
334
+ priceImpact: {
335
+ label: "Price impact",
336
+ tooltip: "Price impact reflects the difference between the expected price and the final execution price, influenced by trade size and available liquidity. Larger trades may move the market price during execution.",
337
+ finalCost: "The final cost reflects price impact and may vary depending on market and network conditions. Larger trade sizes typically benefit from lower relative costs."
338
+ },
339
+ slippage: {
340
+ label: "Max slippage",
341
+ auto: "Auto",
342
+ tooltip: "Slippage represents price changes that can occur while a transaction is being processed. Slippage is dynamically adjusted per trading pair to support reliable execution during market movements.",
343
+ finalCost: "The final cost includes any slippage and may change based on real-time network conditions. Costs are generally reduced for larger transaction amounts."
344
+ },
345
+ processingTime: {
346
+ label: "Processing time",
347
+ lessThanMinutes: "< {{minutes}} min",
348
+ lessThanHours: "< {{hours}} hr"
349
+ },
350
+ minDeposit: {
351
+ label: "min",
352
+ tooltip: "The minimum amount you can deposit on the selected network."
353
+ },
354
+ help: {
355
+ needHelp: "Need help?",
356
+ contactSupport: "Contact support"
357
+ },
358
+ terms: {
359
+ termsApply: "Terms apply"
360
+ },
361
+ supportedToken: "Supported token",
362
+ supportedChain: "Supported chain",
363
+ depositAddress: {
364
+ label: "Your deposit address",
365
+ tooltip: "Send any supported token to this address, and it will be automatically converted to {{token}} in your account."
366
+ },
367
+ copyAddress: "Copy address",
368
+ copied: "Copied!",
369
+ loading: "Loading...",
370
+ loadingQRCode: "Loading QR Code...",
371
+ noAddressAvailable: "No address available",
372
+ noChainsAvailable: "No chains available for this token"
373
+ },
374
+ depositModal: {
375
+ transferCrypto: {
376
+ title: "Transfer Crypto",
377
+ subtitle: "No limit \u2022 Instant"
378
+ },
379
+ depositWithCard: {
380
+ title: "Deposit with Card",
381
+ subtitle: "$50,000 limit \u2022 2 min"
382
+ },
383
+ quotes: "Quotes"
384
+ },
385
+ buyWithCard: {
386
+ onramp: {
387
+ completeTransaction: "Complete transaction with {{provider}}",
388
+ canCloseModal: "You can close this modal.",
389
+ youUse: "You use",
390
+ youBuy: "You buy",
391
+ youReceive: "You receive",
392
+ intentAddressNote: "The wallet address displayed in the payment provider is a temporary deposit address. Your funds will be automatically converted and deposited into your account."
393
+ }
394
+ }
395
+ };
396
+
397
+ // src/lib/i18n.ts
398
+ var i18n = en_default;
399
+ // Annotate the CommonJS export names for ESM import in node:
400
+ 0 && (module.exports = {
401
+ ExecutionStatus,
402
+ SOLANA_USDC_ADDRESS,
403
+ createDepositAddress,
404
+ createMeldSession,
405
+ getApiBaseUrl,
406
+ getChainName,
407
+ getFiatCurrencies,
408
+ getIconUrl,
409
+ getIconUrlWithCdn,
410
+ getMeldQuotes,
411
+ getPreferredIconUrl,
412
+ getProjectConfig,
413
+ getSupportedDepositTokens,
414
+ getTokenChains,
415
+ getWalletByChainType,
416
+ i18n,
417
+ queryExecutions,
418
+ setApiConfig,
419
+ useUserIp
420
+ });