@brahmafi/cards-sdk
Version:
Official SDK for integrating Swype payment and credit services
1,508 lines (1,487 loc) • 516 kB
JavaScript
// src/widgets/kyc/KycModal.tsx
import { useMemo, useEffect as useEffect3 } from "react";
// src/components/Modal.tsx
import { motion, AnimatePresence } from "framer-motion";
// src/components/SDKWrapper.tsx
import { jsx } from "react/jsx-runtime";
function SDKWrapper({ children, className = "" }) {
return /* @__PURE__ */ jsx("div", { className: `swype-sdk-root ${className}`, children });
}
// src/components/Modal.tsx
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
function Modal({
title,
children,
onClose,
onOutsideClick,
overlayOpacity = "bg-black bg-opacity-100",
topDistance = "pt-[100px]",
open = true,
padding
// Accept the padding prop
}) {
const childrenPadding = padding ?? "px-4 sm:px-6 py-4 sm:py-6";
return /* @__PURE__ */ jsx2(SDKWrapper, { children: /* @__PURE__ */ jsx2(AnimatePresence, { children: open && /* @__PURE__ */ jsx2(
motion.div,
{
initial: { opacity: 0 },
animate: { opacity: 1 },
exit: { opacity: 0 },
transition: { duration: 0.2 },
className: `fixed inset-0 z-50 flex items-start justify-center ${topDistance} ${overlayOpacity} px-4 sm:px-0`,
onClick: onOutsideClick,
"aria-modal": "true",
role: "dialog",
children: /* @__PURE__ */ jsxs(
motion.div,
{
initial: { scale: 0.95, opacity: 0 },
animate: { scale: 1, opacity: 1 },
exit: { scale: 0.95, opacity: 0 },
transition: { duration: 0.2 },
className: "relative max-h-[90vh] w-full max-w-lg p-0 flex flex-col",
onClick: (e) => e.stopPropagation(),
children: [
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pb-[14px]", children: [
/* @__PURE__ */ jsx2("h2", { className: "text-base sm:text-lg font-semibold text-[#E6E8ED]", children: title }),
/* @__PURE__ */ jsx2(
"button",
{
onClick: onClose,
"aria-label": "Close modal",
className: "text-gray-400 hover:text-white text-xl sm:text-2xl px-2",
children: "\xD7"
}
)
] }),
/* @__PURE__ */ jsx2(
"div",
{
style: { maxHeight: "70vh" },
className: "border border-[#292930] rounded-[9px] bg-[#0D0D10] shadow-lg flex flex-col overflow-y-auto [&::-webkit-scrollbar]:w-1.5 sm:[&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-[#292930] [&::-webkit-scrollbar-track]:border-0 [&::-webkit-scrollbar-thumb]:bg-[#808080] [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:border-0",
children: /* @__PURE__ */ jsx2("div", { className: `${childrenPadding} relative`, children })
}
)
]
}
)
}
) }) });
}
// src/stores/cardStatusStore.ts
import { create as create8 } from "zustand";
// src/stores/sdkConfigStore.ts
import { create as create7 } from "zustand";
// src/api/api.ts
import axios3 from "axios";
// src/api/httpClient.ts
import axios2 from "axios";
// src/api/auth.ts
import axios from "axios";
var AUTH_VERSION = "1";
function createLoginTypedData(timestamp, tenantID) {
return {
types: {
EIP712Domain: [
{ name: "name", type: "string" },
{ name: "version", type: "string" }
],
Login: [
{ name: "timestamp", type: "uint256" },
{ name: "tenantID", type: "string" }
]
},
primaryType: "Login",
domain: {
name: "BrahmaCards",
version: AUTH_VERSION
},
message: {
timestamp,
tenantID
}
};
}
function createAuthClient(baseUrl, apiPath, apiKey, tenantId) {
return axios.create({
baseURL: `${baseUrl}${apiPath}/cards/auth`,
headers: {
"Content-Type": "application/json",
"X-Api-Key": apiKey,
"ngrok-skip-browser-warning": "true",
"X-Partner-ID": tenantId
}
});
}
function ensureSDKInitialized(requiredFields = []) {
const state = useSDKConfigStore.getState();
if (!state.isInitialized) {
throw new Error("SwypeSDK not initialized. Call initializeSwypeSDK first.");
}
for (const field of requiredFields) {
if (!state[field]) {
throw new Error(`Missing required SDK config field: ${field}`);
}
}
return state;
}
async function authRequest(path, payload) {
const { apiKey, baseUrl, apiPath, tenantId, setJWT } = ensureSDKInitialized([
"apiKey",
"baseUrl",
"apiPath",
"tenantId"
]);
if (!baseUrl || !apiPath || !apiKey || !tenantId) {
throw new Error("Missing required SDK config fields.");
}
const client = createAuthClient(baseUrl, apiPath, apiKey, tenantId);
const {
data: { data: jwt }
} = await client.post(path, payload);
if (!jwt.accessToken || !jwt.refreshToken || !jwt.expiresIn || !jwt.tokenType) {
throw new Error(`Auth request failed for ${path}`);
}
const enrichedJwt = {
...jwt,
createdAt: Date.now()
};
setJWT(enrichedJwt);
return enrichedJwt;
}
async function generateAuthSign(tenantID, signTypedData) {
const timestamp = Math.floor(Date.now() / 1e3);
const typedData = createLoginTypedData(timestamp, tenantID);
const signature = await signTypedData(typedData);
return { signature, timestamp };
}
async function initializeAuth(signature, timestamp, config) {
const { setJWT } = useSDKConfigStore.getState();
const { eoaAddress, tenantId, apiKey, baseUrl, apiPath } = config;
if (!baseUrl || !apiPath || !apiKey || !tenantId || !eoaAddress) {
throw new Error("Missing required auth configuration fields.");
}
const client = createAuthClient(baseUrl, apiPath, apiKey, tenantId);
const {
data: { data: jwt }
} = await client.post("/sig/login", {
sig: signature,
eoa: eoaAddress,
timestamp,
version: AUTH_VERSION
});
if (!jwt.accessToken || !jwt.refreshToken || !jwt.expiresIn || !jwt.tokenType) {
throw new Error("Auth request failed for /sig/login");
}
const enrichedJwt = {
...jwt,
createdAt: Date.now()
};
console.log("SwypeSDK auth initialized");
setJWT(enrichedJwt);
return enrichedJwt;
}
async function refreshAuth(refreshToken, config) {
const { setJWT } = useSDKConfigStore.getState();
const { eoaAddress, tenantId, apiKey, baseUrl, apiPath } = config;
if (!baseUrl || !apiPath || !apiKey || !tenantId || !eoaAddress) {
throw new Error("Missing required auth configuration fields.");
}
const client = createAuthClient(baseUrl, apiPath, apiKey, tenantId);
if (!refreshToken) {
throw new Error("No refresh token available.");
}
try {
const {
data: { data: jwt }
} = await client.post("/token/refresh", {
refreshToken
});
if (!jwt.accessToken || !jwt.refreshToken || !jwt.expiresIn || !jwt.tokenType) {
throw new Error(
"Auth request failed for /token/refresh: Incomplete JWT received."
);
}
const enrichedJwt = {
...jwt,
createdAt: Date.now()
};
console.log("SwypeSDK auth initialized");
setJWT(enrichedJwt);
return enrichedJwt;
} catch (error) {
console.error("Error refreshing authentication tokens:", error);
throw new Error(
`Failed to refresh authentication tokens: ${error instanceof Error ? error.message : "An unknown error occurred."}`
);
}
}
async function ensureValidAuth() {
const { jwt } = ensureSDKInitialized(["jwt"]);
if (!jwt?.accessToken || !jwt.expiresIn || !jwt.createdAt) {
throw new Error("Authentication missing or incomplete.");
}
const now = Math.floor(Date.now() / 1e3);
const expiry = jwt.expiresIn;
if (now >= expiry) {
throw new Error("Authentication expired. Please refresh.");
}
}
async function beginPasskeyRegistration() {
try {
const client = getApiClient();
const {
data: {
data: { publicKey: registrationOptions }
}
} = await client.get("/cards/auth/passkeys/register/begin");
if (!registrationOptions) {
throw new Error("Invalid server response: registration options missing.");
}
return registrationOptions;
} catch (err) {
console.error("\u274C Error in beginPasskeyRegistration:", err);
throw new Error(
`Passkey registration begin failed: ${err?.message || "Unknown error"}`
);
}
}
async function finishPasskeyRegistration(options) {
if (!options.response || !options.credentialName) {
return {
success: false,
message: "Missing required options for passkey registration finish."
};
}
try {
const client = getApiClient();
const response = await client.post(
"/cards/auth/passkeys/register/finish",
{
response: options.response,
credentialName: options.credentialName
}
);
const {
data: { data: result }
} = response;
const success = response.status === 200;
return {
success,
message: success ? "Passkey registration completed successfully." : `Passkey registration failed: ${result?.status || "Unknown error"}`
};
} catch (err) {
console.error("\u274C Error in finishPasskeyRegistration:", err);
return {
success: false,
message: `Passkey registration finish failed: ${err?.message || "Unknown error"}`
};
}
}
async function beginDiscoverablePasskeyLogin() {
const { apiKey, baseUrl, apiPath, tenantId } = ensureSDKInitialized([
"apiKey",
"baseUrl",
"apiPath",
"tenantId"
]);
if (!baseUrl || !apiPath || !apiKey || !tenantId) {
throw new Error("Missing required SDK config fields.");
}
try {
const client = createAuthClient(baseUrl, apiPath, apiKey, tenantId);
const {
data: { data: response }
} = await client.post(
"/passkeys/login/discoverable/begin",
{}
);
if (!response?.sessionId || !response?.options?.publicKey) {
throw new Error(
"Invalid server response: sessionId or publicKey missing."
);
}
return response;
} catch (err) {
console.error("\u274C Error in beginDiscoverablePasskeyLogin:", err);
throw new Error(
`Discoverable passkey login begin failed: ${err?.message || "Unknown error"}`
);
}
}
async function finishDiscoverablePasskeyLogin(options) {
try {
const jwt = await authRequest("/passkeys/login/discoverable/finish", {
sessionId: options.sessionId,
response: options.response
});
if (!jwt?.accessToken) {
throw new Error("Invalid server response: JWT missing.");
}
console.log("\u2705 SwypeSDK discoverable passkey login completed");
return jwt;
} catch (err) {
console.error("\u274C Error in finishDiscoverablePasskeyLogin:", err);
throw new Error(
`Discoverable passkey login finish failed: ${err?.message || "Unknown error"}`
);
}
}
var getPasskeys = async () => {
try {
const client = getApiClient();
const response = await client.get(
"/cards/auth/passkeys"
);
return response.data.data || [];
} catch (error) {
console.error("[getPasskeys]", error);
return [];
}
};
var deletePasskey = async (id) => {
try {
const client = getApiClient();
const response = await client.delete(
`/cards/auth/passkeys/${id}`
);
return response.data.data;
} catch (error) {
console.error("[deletePasskey]", error);
throw error;
}
};
// src/api/httpClient.ts
var refreshPromise = null;
async function refreshTokenIfNeeded() {
if (!refreshPromise) {
const { jwt, tenantId, apiKey, baseUrl, apiPath } = useSDKConfigStore.getState();
if (!jwt?.refreshToken) {
throw new Error("No refresh token available in SDK configuration store.");
}
if (!jwt?.eoa || !tenantId || !apiKey || !baseUrl || !apiPath) {
throw new Error("Missing required SDK configuration for token refresh.");
}
refreshPromise = refreshAuth(jwt.refreshToken, {
eoaAddress: jwt.eoa,
tenantId,
apiKey,
baseUrl,
apiPath
}).finally(() => {
refreshPromise = null;
});
}
return refreshPromise;
}
function applyAuthHeaders(config) {
const { jwt, apiKey, tenantId } = useSDKConfigStore.getState();
if (!apiKey) throw new Error("Missing API key.");
if (!jwt?.accessToken) throw new Error("Missing access token.");
config.headers.set("Authorization", `Bearer ${jwt.accessToken}`);
config.headers.set("X-Api-Key", apiKey);
config.headers.set("Content-Type", "application/json");
config.headers.set("ngrok-skip-browser-warning", "true");
if (tenantId) {
config.headers.set("X-Partner-ID", tenantId);
}
return config;
}
function getApiClient() {
const { isInitialized, apiKey, jwt, baseUrl, apiPath, clearJWT } = useSDKConfigStore.getState();
if (!isInitialized || !apiKey) {
throw new Error("SwypeSDK not initialized. Call initializeSwypeSDK first.");
}
if (!jwt?.accessToken) {
throw new Error("SwypeSDK auth not ready. Missing access token.");
}
const client = axios2.create({
baseURL: `${baseUrl}${apiPath}`
});
client.interceptors.request.use(
async (config) => {
try {
await ensureValidAuth();
} catch {
try {
await refreshTokenIfNeeded();
} catch (err) {
clearJWT();
throw err;
}
}
return applyAuthHeaders(config);
},
(error) => Promise.reject(error)
);
client.interceptors.response.use(
(response) => response,
async (error) => {
const { response, config } = error;
if (response && config && (response.status === 401 || response.status === 403)) {
try {
await refreshTokenIfNeeded();
return client(applyAuthHeaders(config));
} catch (refreshError) {
clearJWT();
return Promise.reject(refreshError);
}
}
return Promise.reject(error);
}
);
return client;
}
// src/api/utils.ts
import forge from "node-forge";
import { v4 } from "uuid";
// src/config/creditRegistry.ts
var BASE_CHAIN_ID = 8453;
var HYPER_EVM_CHAIN_ID = 999;
var CREDIT_REGISTRY = {
// Borrow Mode
"aave-v3": {
id: "aave-v3",
storeKey: "aave",
providerKey: "aave",
displayName: "Aave",
chainId: BASE_CHAIN_ID,
decimals: 6,
creditType: "borrow",
config: {
borrowTokenAddress: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"
},
minDelegateAmount: 1,
icon: "AaveIcon",
canDCA: false
},
euler: {
id: "euler",
storeKey: "euler",
providerKey: "euler",
displayName: "Euler",
chainId: BASE_CHAIN_ID,
decimals: 18,
creditType: "borrow",
config: {
borrowVaultAddress: "0x0A1a3b5f2041F33522C4efc754a7D096f880eE16"
},
icon: "EulerIcon",
canDCA: false
},
hypurrFi: {
id: "hypurrFi",
storeKey: "hypurrFi",
providerKey: "hypurrfi",
displayName: "HypurrFi",
chainId: HYPER_EVM_CHAIN_ID,
decimals: 6,
creditType: "borrow",
config: {
borrowTokenAddress: "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb"
},
minDelegateAmount: 1,
icon: "HypurrFiIcon",
canDCA: false
},
// Spend Mode
"hypurrFi-withdraw": {
id: "hypurrFi-withdraw",
storeKey: "hypurrFiWithdraw",
providerKey: "hypurrFi-withdraw",
displayName: "HypurrFi",
chainId: HYPER_EVM_CHAIN_ID,
decimals: 6,
creditType: "spend",
config: {
aTokenAddress: "0x0000000000000000000000000000000000000000"
},
minDelegateAmount: 1,
icon: "HypurrFiIcon",
canDCA: true
},
"felix-withdraw": {
id: "felix-withdraw",
storeKey: "felixWithdraw",
providerKey: "felix-withdraw",
displayName: "Felix",
chainId: HYPER_EVM_CHAIN_ID,
decimals: 6,
creditType: "spend",
config: {
vaultTokenAddress: "0x0000000000000000000000000000000000000000"
},
minDelegateAmount: 1,
icon: "FelixIcon",
canDCA: true
},
"hyperBeat-withdraw": {
id: "hyperBeat-withdraw",
storeKey: "hyperBeatWithdraw",
providerKey: "hyperBeat-withdraw",
displayName: "HyperBeat",
chainId: HYPER_EVM_CHAIN_ID,
decimals: 6,
creditType: "spend",
config: {
vaultTokenAddress: "0x0000000000000000000000000000000000000000"
},
minDelegateAmount: 1,
icon: "HyperBeatIcon",
canDCA: true
},
"hyperLend-withdraw": {
id: "hyperLend-withdraw",
storeKey: "hyperLendWithdraw",
providerKey: "hyperLend-withdraw",
displayName: "HyperLend",
chainId: HYPER_EVM_CHAIN_ID,
decimals: 6,
creditType: "spend",
config: {
aTokenAddress: "0x0000000000000000000000000000000000000000"
},
minDelegateAmount: 1,
icon: "HyperLendIcon",
canDCA: true
}
};
var getCreditProvider = (id) => {
const provider = CREDIT_REGISTRY[id];
if (!provider) {
console.error(
`Unsupported credit provider: ${id}. Supported providers: ${Object.keys(
CREDIT_REGISTRY
).join(", ")}`
);
return null;
}
return provider;
};
var getAllCreditProviders = () => {
return Object.values(CREDIT_REGISTRY);
};
var getCreditProviderByStoreKey = (storeKey) => {
return Object.values(CREDIT_REGISTRY).find((p) => p.storeKey === storeKey);
};
var getCreditProviderByProviderKey = (providerKey) => {
return Object.values(CREDIT_REGISTRY).find(
(p) => p.providerKey === providerKey
);
};
var mapApiTypeToStoreKey = (apiCreditType) => {
const provider = getCreditProvider(apiCreditType);
return provider ? provider.storeKey : null;
};
var mapStoreKeyToApiType = (storeKey) => {
const provider = getCreditProviderByStoreKey(storeKey);
return provider ? provider.id : void 0;
};
var getProviderConfig = (creditType) => {
const provider = getCreditProvider(creditType);
return provider ? provider.config : null;
};
var getProviderDecimals = (creditType) => {
const provider = getCreditProvider(creditType);
return provider ? provider.decimals : null;
};
var getCreditProvidersByType = (creditType, chainId) => {
let providers = Object.values(CREDIT_REGISTRY).filter(
(p) => p.creditType === creditType
);
if (chainId) {
providers = providers.filter((p) => p.chainId === chainId);
}
return providers;
};
var isCreditProviderOfType = (creditProviderId, creditType) => {
const provider = getCreditProvider(creditProviderId);
return provider ? provider.creditType === creditType : false;
};
// src/api/utils.ts
import React from "react";
// src/components/icons/USDT0Icon.tsx
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
function USDT0Icon({ width = 40, height = 40 }) {
return /* @__PURE__ */ jsxs2(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
width,
height,
viewBox: "0 0 976 976",
fill: "none",
children: [
/* @__PURE__ */ jsx3("circle", { cx: "488.008", cy: "488.324", r: "487.965", fill: "#00B988" }),
/* @__PURE__ */ jsx3(
"path",
{
d: "M238.48 233.252H737.533V344.152H543.459V455.054H432.557V344.152H238.48V233.252Z",
fill: "white"
}
),
/* @__PURE__ */ jsx3(
"path",
{
d: "M432.557 455.054V676.856H321.656V455.054H432.557Z",
fill: "white"
}
),
/* @__PURE__ */ jsx3(
"path",
{
d: "M543.475 676.856H654.36V455.054H543.459V676.856H432.574V787.757H543.475V676.856Z",
fill: "white"
}
)
]
}
);
}
// src/components/icons/USDeIcon.tsx
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
function USDeIcon({ width = 40, height = 40 }) {
return /* @__PURE__ */ jsxs3(
"svg",
{
xmlns: "http://www.w3.org/2000/svg",
width,
height,
viewBox: "0 0 21 20",
fill: "none",
children: [
/* @__PURE__ */ jsxs3("g", { clipPath: "url(#clip0_59965_324299)", children: [
/* @__PURE__ */ jsx4(
"path",
{
d: "M10.4703 0.650391H10.4707C15.5658 0.650391 19.6962 4.82513 19.6963 9.97499V9.9754C19.6963 15.1253 15.5658 19.3002 10.4707 19.3002H10.4703C5.37519 19.3001 1.24487 15.1253 1.24487 9.9754V9.97499C1.24491 4.82515 5.37521 0.650426 10.4703 0.650391Z",
fill: "black",
stroke: "black",
strokeWidth: "1.27786"
}
),
/* @__PURE__ */ jsx4(
"path",
{
fillRule: "evenodd",
clipRule: "evenodd",
d: "M8.96334 2.16016C5.33664 2.86622 2.59718 6.09122 2.59717 9.96301C2.59717 13.8348 5.33664 17.06 8.96334 17.7661V17.0213C5.73812 16.3263 3.31905 13.4302 3.31905 9.96301C3.31907 6.49585 5.73812 3.59969 8.96334 2.90478V2.16016ZM11.9685 2.90771V2.1628C15.5885 2.87422 18.3213 6.09604 18.3213 9.96301C18.3213 13.83 15.5885 17.052 11.9685 17.7634V17.0183C15.1869 16.3182 17.5992 13.4254 17.5992 9.96301C17.5992 6.50069 15.1869 3.60778 11.9685 2.90771Z",
fill: "white"
}
),
/* @__PURE__ */ jsx4(
"path",
{
d: "M11.5793 9.69823C12.1792 9.81378 12.6444 10.0366 12.9751 10.3668C13.3058 10.6887 13.4712 11.1014 13.4712 11.6049V12.3973C13.4712 12.9998 13.2559 13.4868 12.8252 13.8582C12.3945 14.2214 11.8292 14.403 11.1294 14.403H10.8871V15.6658H10.0565V14.403H9.80274C9.3413 14.403 8.9337 14.2998 8.57992 14.0934C8.22615 13.8788 7.94929 13.5817 7.74933 13.202C7.55707 12.8141 7.46094 12.3684 7.46094 11.8649H8.29152C8.29152 12.3766 8.42995 12.7934 8.70681 13.1154C8.99137 13.429 9.36438 13.5858 9.82582 13.5858H11.1063C11.5601 13.5858 11.9254 13.4785 12.2022 13.2639C12.4791 13.0411 12.6175 12.7522 12.6175 12.3973V11.6049C12.6175 11.3242 12.5137 11.0849 12.3061 10.8868C12.1061 10.6887 11.8292 10.5608 11.4755 10.503L9.39897 10.1316C8.81449 10.0242 8.36074 9.80139 8.03774 9.46298C7.71472 9.12457 7.55322 8.6995 7.55322 8.18775V7.51918C7.55322 6.91664 7.76086 6.43791 8.17616 6.08299C8.59915 5.71984 9.15672 5.53825 9.84888 5.53825H10.0565V4.27539H10.8871V5.53825H11.1524C11.8062 5.53825 12.333 5.75285 12.7329 6.18204C13.1328 6.60299 13.3328 7.16014 13.3328 7.85348H12.5022C12.5022 7.39951 12.3791 7.03633 12.133 6.76395C11.8869 6.49157 11.5601 6.35537 11.1524 6.35537H9.84888C9.41052 6.35537 9.06059 6.46267 8.79911 6.67727C8.53761 6.88362 8.40688 7.16426 8.40688 7.51918V8.18775C8.40688 8.47664 8.50302 8.72012 8.69528 8.91822C8.89524 9.11631 9.16825 9.24838 9.51433 9.31441L11.5793 9.69823Z",
fill: "white"
}
)
] }),
/* @__PURE__ */ jsx4("defs", { children: /* @__PURE__ */ jsx4("clipPath", { id: "clip0_59965_324299", children: /* @__PURE__ */ jsx4(
"rect",
{
width: "20",
height: "20",
fill: "white",
transform: "translate(0.5)"
}
) }) })
]
}
);
}
// src/components/icons/USDhlIcon.tsx
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
function USDhlIcon({ width = 40, height = 40 }) {
return /* @__PURE__ */ jsxs4(
"svg",
{
width,
height,
viewBox: "0 0 21 20",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
children: [
/* @__PURE__ */ jsxs4("g", { clipPath: "url(#clip0_59965_324306)", children: [
/* @__PURE__ */ jsx5(
"path",
{
d: "M10.6665 20C16.1894 20 20.6665 15.5228 20.6665 10C20.6665 4.47715 16.1894 0 10.6665 0C5.14366 0 0.666504 4.47715 0.666504 10C0.666504 15.5228 5.14366 20 10.6665 20Z",
fill: "#BC8827"
}
),
/* @__PURE__ */ jsx5(
"path",
{
fillRule: "evenodd",
clipRule: "evenodd",
d: "M9.71793 2.66406C8.76149 2.7207 7.89442 3.06735 7.31764 3.62369C7.11614 3.81798 6.97143 3.90831 6.7258 3.99281C6.54626 4.05465 6.4139 4.12615 6.43022 4.15255C6.44752 4.18055 6.43465 4.18488 6.39926 4.16299C6.36358 4.1409 6.17553 4.20759 5.94128 4.32539C5.48406 4.55531 4.93694 5.02786 4.69987 5.39772C4.51371 5.68812 4.28712 6.25867 4.23766 6.56154C4.21186 6.71965 4.13287 6.86384 3.9439 7.09798C3.25349 7.95332 2.99131 9.09798 3.21645 10.274C3.26218 10.5127 3.35261 10.8342 3.41744 10.9885C3.51515 11.2209 3.53537 11.3502 3.53552 11.7436C3.53561 12.2765 3.67803 12.9096 3.89493 13.3417C3.96388 13.4791 4.02028 13.609 4.02028 13.6303C4.02028 13.7023 4.2814 14.0602 4.59149 14.4133C4.81329 14.6657 5.01719 14.8341 5.32055 15.0152C5.8278 15.318 5.92178 15.3988 6.13184 15.713C6.48643 16.2432 7.20338 16.816 7.82815 17.0682C8.31011 17.2629 9.07603 17.3315 9.65798 17.2323C10.0746 17.1612 10.0907 17.1621 10.4823 17.2798C11.0564 17.4523 11.9372 17.4603 12.4559 17.2977C12.9325 17.1483 13.3925 16.9149 13.3491 16.8445C13.3285 16.8113 13.3374 16.8036 13.3718 16.8249C13.4406 16.8675 13.6884 16.7029 13.8986 16.4749C14.017 16.3464 14.1104 16.2968 14.2865 16.2688C14.5815 16.2219 15.3951 15.8705 15.3798 15.7965C15.3734 15.7659 15.3955 15.7512 15.4288 15.764C15.5151 15.7972 16.0819 15.3127 16.3726 14.9575C16.5078 14.7922 16.6864 14.5174 16.7695 14.3468C16.9165 14.0452 17.1117 13.3505 17.1123 13.1268C17.1126 13.0659 17.2301 12.8475 17.3736 12.6414C18.0236 11.7082 18.2716 10.8206 18.175 9.77327C18.1323 9.31005 18.0156 8.96861 17.713 8.42183C17.5739 8.17028 17.5468 8.07321 17.5505 7.83936C17.5574 7.39838 17.3924 6.73298 17.1616 6.27131C16.8824 5.71277 16.2533 5.08228 15.6703 4.77673C15.3095 4.58759 15.2501 4.53546 15.0606 4.24234C14.6945 3.67582 13.9552 3.17496 13.1063 2.91845C12.6537 2.78162 12.5847 2.77404 11.8515 2.78132C11.2917 2.78686 10.9769 2.76715 10.7209 2.71061C10.3827 2.63586 10.2769 2.63096 9.71793 2.66406ZM10.1916 2.71259C10.1588 2.72589 10.0933 2.72672 10.0461 2.71439C9.99896 2.70207 10.0258 2.69119 10.1059 2.69022C10.1859 2.68925 10.2244 2.6993 10.1916 2.71259ZM9.88614 2.87762C9.82132 2.99897 9.8035 3.00479 9.38327 3.04289L9.04867 3.07328L9.12241 2.96193C9.20379 2.83908 9.35741 2.79224 9.70746 2.78356C9.92729 2.77812 9.93672 2.78307 9.88614 2.87762ZM10.5641 2.83039C10.6988 2.85928 10.809 2.89917 10.809 2.91903C10.809 2.93883 10.7589 3.00212 10.6978 3.05959C10.5911 3.15986 10.5738 3.16147 10.2734 3.09832C9.95953 3.03231 9.91965 2.98742 10.043 2.83865C10.1049 2.764 10.2445 2.76181 10.5641 2.83039ZM12.4698 2.8585C12.4364 2.87199 12.3819 2.87199 12.3485 2.8585C12.3152 2.84505 12.3425 2.83404 12.4091 2.83404C12.4758 2.83404 12.5031 2.84505 12.4698 2.8585ZM9.01482 2.91417C9.01482 3.02426 8.86143 3.13239 8.62453 3.18923C8.47913 3.22413 8.31942 3.26932 8.26971 3.28956C8.18971 3.32217 8.18563 3.31446 8.23442 3.22316C8.29787 3.10444 8.40982 3.03726 8.69304 2.94781C8.93701 2.87078 9.01482 2.86268 9.01482 2.91417ZM12.1773 2.92276C12.3304 2.92397 12.2145 3.05643 12.0348 3.08565C11.9153 3.10507 11.8158 3.08784 11.7188 3.03085L11.5772 2.94771L11.7386 2.9167C11.8274 2.89966 11.9436 2.89388 11.9969 2.90388C12.0503 2.91393 12.1314 2.92242 12.1773 2.92276Z",
fill: "white"
}
)
] }),
/* @__PURE__ */ jsx5("defs", { children: /* @__PURE__ */ jsx5("clipPath", { id: "clip0_59965_324306", children: /* @__PURE__ */ jsx5(
"rect",
{
width: "20",
height: "20",
fill: "white",
transform: "translate(0.666504)"
}
) }) })
]
}
);
}
// src/api/utils.ts
var formatUnits = (value, decimals) => {
const divisor = BigInt(10 ** decimals);
const quotient = value / divisor;
const remainder = value % divisor;
const formattedRemainder = remainder.toString().padStart(decimals, "0");
return `${quotient.toString()}.${formattedRemainder}`;
};
function resolveDecimals(creditType, baseTokenAddress) {
if (baseTokenAddress) {
const token = VAULT_TOKENS[baseTokenAddress.toLowerCase()];
if (token) return token.decimals;
}
const decimals = getProviderDecimals(creditType);
return decimals ?? 6;
}
function formatAvailableLimit(availableLimit, creditType, baseTokenAddress) {
const decimals = resolveDecimals(creditType, baseTokenAddress);
const formatted = formatUnits(BigInt(availableLimit), decimals);
return parseFloat(Number(formatted).toFixed(4));
}
function mapEulerMetadataToSuppliedAssets(metadata) {
if (!Array.isArray(metadata?.vaults)) return metadata;
const suppliedAssets = metadata.vaults.map((vault) => {
const formattedAsset = Number(formatUnits(BigInt(vault.assets || 0), 18));
return {
UsageAsCollateralEnabledOnUser: true,
// Assume true for Euler
amount: formattedAsset,
amountUSD: 0,
// No USD value provided, set to 0 or calculate if possible
collateralAmountBase: String(formattedAsset),
collateralAmountBig: formattedAsset,
supplyRate: 0,
// Not provided by Euler, set to 0 or fetch if available
underlyingAsset: vault.vault || ""
};
});
const suppliedValue = suppliedAssets.reduce(
(sum, asset) => sum + asset.amountUSD,
0
);
return {
...metadata,
suppliedAssets,
suppliedValue
};
}
function encryptPinWithSessionKey(pin, sessionKey) {
const hexLength = pin.length.toString(16);
const formattedPin = `2${hexLength}${pin}${"F".repeat(14 - pin.length)}`;
const ivBytes = forge.random.getBytesSync(16);
const encodedIV = forge.util.encode64(ivBytes);
const keyBytes = forge.util.hexToBytes(sessionKey);
const cipher = forge.cipher.createCipher("AES-GCM", keyBytes);
cipher.start({ iv: ivBytes });
cipher.update(forge.util.createBuffer(formattedPin));
cipher.finish();
const encrypted = cipher.output.getBytes() + cipher.mode.tag.getBytes();
const encodedEncrypted = forge.util.encode64(encrypted);
return {
iv: encodedIV,
data: encodedEncrypted
};
}
function getCardSolverConfig(creditType) {
const config = getProviderConfig(creditType);
return config ?? {};
}
var mapNewStatusToLegacyCardStatus = (kycStatus, rainStatus, errorDetails) => {
if (errorDetails) {
return "error";
}
if (rainStatus === "approved") {
return "approved";
}
if (kycStatus === "not_requested" || kycStatus === "requested") {
return "userNotExisting";
}
if (kycStatus === "rejected") {
return "rejected";
}
if (kycStatus === "resubmitted" || kycStatus === "onhold") {
return "resubmit";
}
if (kycStatus === "pending") {
return "pending";
}
if (kycStatus === "approved") {
if (rainStatus === "review" || rainStatus === "pending" || rainStatus === "initiated") {
return "pending";
}
if (rainStatus === "rejected") {
return "rejected";
}
}
return "initiated";
};
var USDHL_ADDRESS = "0xb50a96253abdf803d85efcdce07ad8becbc52bd5";
var USDE_ADDRESS = "0x5d3a1ff2b6bab83b63cd9ad0787074081a52ef34";
var USDT0_ADDRESS = "0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb";
var VAULT_TOKENS = {
[USDT0_ADDRESS]: { symbol: "USD\u20AE0", decimals: 6 },
[USDE_ADDRESS]: { symbol: "USDe", decimals: 18 },
[USDHL_ADDRESS]: { symbol: "USDhl", decimals: 6 }
};
var getVaultTokenIcon = (size = 26) => ({
[USDHL_ADDRESS]: {
icon: React.createElement(USDhlIcon, { width: size, height: size }),
symbol: "USDhl",
decimals: 6
},
[USDE_ADDRESS]: {
icon: React.createElement(USDeIcon, { width: size, height: size }),
symbol: "USDe",
decimals: 18
},
[USDT0_ADDRESS]: {
icon: React.createElement(USDT0Icon, { width: size, height: size }),
symbol: "USD\u20AE0",
decimals: 6
}
});
// src/api/api.ts
var extractErrorMessage = (error, fallback = "Unexpected error") => error?.response?.data?.data?.error || error?.response?.data?.message || error?.message || fallback;
var getCardStatus = async () => {
try {
const client = getApiClient();
const response = await client.get(
`/cards/users/status`
);
const { kycStatus, rainStatus, errorDetails } = response.data.data;
const legacyStatus = mapNewStatusToLegacyCardStatus(
kycStatus,
rainStatus,
errorDetails
);
return { data: legacyStatus };
} catch (error) {
if (axios3.isAxiosError(error) && error.response?.status === 404) {
return { data: "userNotExisting" };
}
throw error;
}
};
var getUserCards = async () => {
try {
const client = getApiClient();
const response = await client.get(`/cards`);
return response.data;
} catch (err) {
console.error("[getUserCards]", err);
return { data: null };
}
};
var getCreditInformation = async (solverType, chainID, userConfig) => {
try {
const client = getApiClient();
const config = userConfig ?? getProviderConfig(solverType) ?? {};
const response = await client.post(
`/cards/users/credit`,
{
solverType,
config,
chainID
}
);
if (response.data?.data && typeof response.data.data.availableLimit === "number") {
response.data.data.availableLimit = formatAvailableLimit(
response.data.data.availableLimit,
solverType,
userConfig?.purchaseBaseTokenAddress || void 0
);
response.data.data.amountDelegated = formatAvailableLimit(
response.data.data.amountDelegated,
solverType,
userConfig?.purchaseBaseTokenAddress || void 0
);
}
if (solverType === "euler" && response.data?.data?.metadata) {
response.data.data.metadata = mapEulerMetadataToSuppliedAssets(
response.data.data.metadata
);
}
return response.data;
} catch (error) {
console.error("[getCreditInformation]", error);
return { data: null };
}
};
var getSumSubAccessToken = async (userId, ipAddress) => {
try {
const client = getApiClient();
const response = await client.post(
"/cards/sumsub/token",
{ ownerAddress: userId, ipAddress }
);
return response.data.data;
} catch (error) {
console.error("[error at getSumSubAccessToken]", error);
return void 0;
}
};
var getCreditDelegationTxData = async (requestData, solverParams) => {
const payload = {
creditType: requestData.creditType,
creditLimit: requestData.creditLimit,
chainID: requestData.chainID,
userParams: {
...requestData.userParams,
...solverParams ?? {}
}
};
const client = getApiClient();
const response = await client.post(
`/cards/users/credit/delegate`,
payload
);
return response.data;
};
var updateCard = async (requestData) => {
try {
const client = getApiClient();
const cardSolverConfig = isCreditProviderOfType(
requestData.creditType,
"spend"
) ? { ...requestData.config } : getCardSolverConfig(requestData.creditType);
const response = await client.patch(`/cards/creditprovider`, {
creditProviderAddress: requestData.creditProviderAddress,
chainID: requestData.chainId,
solverType: requestData.creditType,
cardID: requestData.cardID,
cardSolverConfig
});
if (response.status === 200) {
return { success: true };
}
return {
success: false,
message: response.data?.message || "Failed to update card"
};
} catch (error) {
console.error("[updateCard]", error);
return {
success: false,
message: error?.response?.data?.data?.error || error?.message || "Failed to update card"
};
}
};
var createCard = async (userEoa, chainID, solverType, cardSolverConfig) => {
const client = getApiClient();
const response = await client.post(`/cards/create`, {
creditProviderAddress: userEoa,
chainID,
solverType,
cardSolverConfig
});
return response.data;
};
var initializeUserConfig = async (chainID, solverType, config) => {
const client = getApiClient();
try {
const response = await client.post(`/cards/users`, {
solverType,
config,
chainID
});
if (response.status === 200) {
return { success: true };
}
return {
success: false,
message: "Configuration initialized successfully."
};
} catch (err) {
return {
success: false,
message: err?.response?.data?.data?.error || err?.message || "Failed to initialize configuration."
};
}
};
var getUserConfig = async () => {
try {
const client = getApiClient();
const response = await client.get(
`/cards/users/preferences`
);
return response.data.data;
} catch (error) {
console.error("Failed to fetch user config:", error);
return null;
}
};
var freezeCard = async (cardID, freeze) => {
const client = getApiClient();
try {
const response = await client.patch(`/cards/status`, {
cardID,
freeze
});
if (response.status === 200) {
return { success: true };
}
return {
success: false,
message: response.data?.message || "Failed to freeze card"
};
} catch (error) {
console.error("[freezeCard]", error);
return {
success: false,
message: error?.response?.data?.data?.error || error?.message || "Failed to freeze card"
};
}
};
var updatePin = async (iv, data, sessionID, cardID) => {
const client = getApiClient();
try {
const response = await client.patch(
`/cards/pin`,
{ pin: { encryptedPin: { data, iv } }, cardID },
{
headers: {
sessionID
}
}
);
if (response.status === 200) {
return { success: true };
}
return {
success: false,
message: response.data?.message || "Failed to update PIN"
};
} catch (error) {
console.error("[updatePin]", error);
return {
success: false,
message: error?.response?.data?.data?.error || error?.message || "Failed to update PIN"
};
}
};
var getCardSecrets = async (cardID, sessionID) => {
const client = getApiClient();
try {
const response = await client.get(`/cards/secrets/${cardID}`, {
headers: {
sessionID
}
});
if (response.status === 200 && response.data?.data) {
return response.data.data;
}
throw new Error("Unexpected response format while fetching card secrets.");
} catch (error) {
console.error("[getCardSecrets]", error);
throw new Error(extractErrorMessage(error, "Failed to fetch card secrets"));
}
};
var getCardLimit = async (cardID) => {
const client = getApiClient();
try {
const response = await client.get(`/cards/limit/${cardID}`);
if (response.status === 200 && response.data?.data) {
return response.data.data;
}
throw new Error("Unexpected response format while fetching card limits.");
} catch (error) {
console.error("[getCardLimit]", error);
throw new Error(extractErrorMessage(error, "Failed to fetch card limits"));
}
};
var updateLimit = async (limit, cardID) => {
const client = getApiClient();
try {
const response = await client.patch(
`/cards/limits`,
{ limit, frequency: "per24HourPeriod", cardID }
);
if (response.status === 200) {
return { success: true };
}
return {
success: false,
message: response.data?.message || "Failed to update limit"
};
} catch (error) {
console.error("[updateLimit]", error);
return {
success: false,
message: extractErrorMessage(error, "Failed to update limit")
};
}
};
var getCardPublicKey = async () => {
const client = getApiClient();
const response = await client.get("/cards/pubkey");
return response.data;
};
var getTransactions = async (cardID, limit, cursor) => {
try {
const client = getApiClient();
const response = await client.get(
`cards/transactions/${cardID}`,
{
params: {
limit,
cursor
}
}
);
return response.data;
} catch (error) {
console.error("[getTransactions]", error);
return {
data: {
transactions: [],
pagination: {
limit: limit || 50,
has_next: false
}
}
};
}
};
var getOnchainTransactionDetails = async (transactionID) => {
try {
const client = getApiClient();
const response = await client.get(
`cards/transactions/${transactionID}/onchain`
);
return response.data;
} catch (error) {
console.error("[getOnchainTransactionDetails]", error);
return { data: [] };
}
};
var getEulerCardPreview = async (vaults) => {
try {
const client = getApiClient();
const creditType = "euler";
const eulerConfig = getProviderConfig(creditType);
const response = await client.post(`/cards/users/credit/${creditType}/preview`, {
vaults,
...eulerConfig,
chainID: BASE_CHAIN_ID
// Euler is only on Base
});
return response.data;
} catch (error) {
console.error("[getEulerCardPreview]", error);
return { data: { credit: "0", collateral: "0" } };
}
};
var getEulerHealthFactor = async () => {
try {
const client = getApiClient();
const creditType = "euler";
const eulerConfig = getProviderConfig(creditType);
if (!eulerConfig?.borrowVaultAddress) {
return { data: { healthFactor: "0" } };
}
const response = await client.get(
`/cards/users/${creditType}/hf/${eulerConfig.borrowVaultAddress}/${BASE_CHAIN_ID}`
);
return response.data;
} catch (error) {
console.error("[getEulerHealthFactor]", error);
return { data: { healthFactor: "0" } };
}
};
var getPendingTransactionBalance = async (cardID) => {
try {
const client = getApiClient();
const response = await client.get(`/cards/transactions/balances/pending/${cardID}`);
return response.data;
} catch (error) {
console.error("[getPendingTransactionBalances]", error);
return { data: { status: "error", balances: { USD: 0 } } };
}
};
var getEulerTotalAsset = async () => {
try {
const client = getApiClient();
const response = await client.get(
`/cards/users/euler/assets/${BASE_CHAIN_ID}`
);
return response.data;
} catch (error) {
console.error("[getEulerTotalAsset]", error);
return { data: { totalAssetsUSD: 0 } };
}
};
var getHookTransactions = async (limit, offset) => {
try {
const client = getApiClient();
const response = await client.get(
"/cards/transactions/hook",
{
params: { limit, offset }
}
);
return response.data.data;
} catch (error) {
console.error("[getHookTransactions]", error);
return [];
}
};
var updateCardHook = async (cardID, chainID, hookType, config) => {
const client = getApiClient();
try {
const response = await client.patch(
`/cards/hook`,
{
cardID,
config,
hookType,
chainID
}
);
if (response.status === 200) {
return { success: true };
}
return {
success: false,
message: response.data?.message || "Failed to update card hook"
};
} catch (error) {
console.error("[updateCardHook] Error:", error);
return {
success: false,
message: error?.response?.data?.data?.error || error?.message || "Failed to update card hook"
};
}
};
var deleteCardHook = async (cardID) => {
const client = getApiClient();
try {
const response = await client.delete(`/cards/hook/${cardID}`);
if (response.status === 200) {
return { success: true };
}
return {
success: false,
message: response.data?.message || "Failed to delete card hook"
};
} catch (error) {
console.error("[deleteCardHook] Error:", error);
return {
success: false,
message: error?.response?.data?.data?.error || error?.response?.data?.message || error?.message || "Failed to delete card hook"
};
}
};
// src/stores/creditStore.ts
import { create } from "zustand";
var getInitialCreditInfo = () => {
const allProviders = getAllCreditProviders();
return allProviders.reduce((acc, provider) => {
acc[provider.storeKey] = null;
return acc;
}, {});
};
var useCreditStore = create((set, get) => ({
creditInfo: {},
// Will be initialized dynamically
isLoading: false,
isRefreshingPositions: false,
error: null,
userConfig: null,
// Internal methods for SDK use only (prefixed with _)
_setCreditInfo: (type, info) => set((state) => ({
creditInfo: {
...state.creditInfo,
[type]: info
}
})),
_setUserConfig: (config) => set({ userConfig: config }),
_setLoading: (loading) => set({ isLoading: loading }),
_setError: (error) => set({ error }),
_reset: () => set({
creditInfo: getInitialCreditInfo(),
// Dynamic reset
isLoading: false,
error: null
}),
// New function to refresh positions for specified credit types
_refreshPositions: async (creditTypes) => {
const { jwt, isInitialized } = useSDKConfigStore.getState();
if (!isInitialized || !jwt?.eoa) {
console.error(
"\u274C SDK: Cannot refresh positions - SDK not initialized or no EOA address"
);
return;
}
console.log("\u{1F504} SDK: Refreshing positions for:", creditTypes);
set({ error: null, isRefreshingPositions: true });
try {
const userCardsResponse = await getUserCards();
const userCard = userCardsResponse.data?.[0] || null;
const userConfig = userCard ? {
solverType: userCard.solverType,
config: userCard.solverConfig
} : await getUserConfig();
const fetchPromises = creditTypes.map((storeKey) => {
const creditType = mapStoreKeyToApiType(storeKey);
if (!creditType) {
throw new Error(`Unknown store key: ${storeKey}`);
}
const provider = getCreditProvider(creditType);
const currentConfig = userConfig?.solverType === provider?.id ? userConfig?.config : void 0;
return getCreditInformation(
creditType,
provider?.chainId ?? BASE_CHAIN_ID,
currentConfig
);
});
const responses = await Promise.all(fetchPromises);
responses.forEach((response, index) => {
const storeKey = creditTypes[index];
get()._setCreditInfo(storeKey, response);
});
console.log(
"\u2705 SDK: Successfully refreshed positions for:",
creditTypes.join(", ")
);
} catch (error) {
console.error("\u274C SDK: Error refreshing positions:", error);
const errorMessage = error instanceof Error ? error.message : "Failed to refresh positions";
set({ error: errorMessage });
} finally {
set({ isRefreshingPositions: false });
}
}
}));
// src/stores/transactionsStore.ts
import { create as create2 } from "zustand";
var useTransactionsStore = create2((set) => ({
transactions: [],
pagination: null,
isLoading: false,
loadingNextPage: false,
initialFetchDone: false,
error: null,
pendingTxnAmount: 0,
// Internal methods for SDK use only (prefixed with _)
_setTransactions: (transactions) => set({ transactions }),
_appendTransactions: (newTransactions) => set((state) => ({
transactions: [...state.transactions, ...newTransactions]
})),
_setPagination: (pagination) => set({ pagination }),
_setLoading: (loading) => set({ isLoading: loading }),
_setLoadingNextPage: (loading) => set({ loadingNextPage: loading }),
_setInitialFetchDone: (done) => set({ initialFetchDone: done }),
_setError: (error) => set({ error }),
_setPendingTxnAmount: (amount) => set({ pendingTxnAmount: amount }),
_reset: () => set({
transactions: [],
pagination: null,
isLoading: false,
loadingNextPage: false,
initialFetchDone: false,
error: null
})
}));
// src/stores/rewardsStore.ts
import { create as create3 } from "zustand";
// src/api/rewards/api.ts
var extractErrorMessage2 = (error, fallback = "Unexpected error") => error?.response?.data?.error?.message || error?.response?.data?.message || error?.message || fallback;
var getReferralStats = async () => {
try {
const client = getApiClient();
const response = await client.get(
"/cards/referrals/code"
);
return response.data;
} catch (error) {
throw new Error(extractErrorMessage2(error, "Failed to get referral stats"));
}
};
var claimReferral = async (referrerCode) => {
try {
const client = getApiClient();
const response = await client.post(
"/cards/referrals/claim",
{ referrerCode }
);
return response.data;
} catch (error) {
throw new Error(extractErrorMessage2(error, "Failed to claim referral"));
}
};
var getReferralEarnings = async (params) => {
try {
const client = getApiClient();
const response = await client.get(
"/cards/rewards/referral-earnings",
{ params }
);
return response.data;
} catch (error) {
throw new Error(
extractErrorMessage2(error, "Failed to get referral earnings")
);
}
};
var getXPBalance = async () => {
try {
const client = getApiClient();
const response = await client.get(
`/cards/rewards/balance`
);
return response.data;
} catch (error) {
throw new Error(extractErrorMessage2(error, "Failed to get XP balance"));
}
};
var getXPHistory = async (params) => {
try {
const client = getApiClient();
const response = await client.get(
"/cards/rewards/history",
{
params
}
);
return response.data;
} catch (error) {
throw new Error(extractErrorMessage2(error, "Failed to get XP history"));
}
};
var claimMilestone = async (milestoneId) => {
try {
const client = getApiClient();
const response = await client.post(
`/cards/milestones/claim/${milestoneId}`
);
return response.data;
} catch (error) {
throw new Error(extractErrorMessage2(error, "Failed to claim milestone"));
}
};
var getMilestoneStatus = async () => {
try {
const client = getApiClient();
const response = await client.get(
`/cards/milestones`
);
return response.data;
} catch (error) {
throw new Error(
extractErr