@kryptos_connect/mobile-sdk
v1.0.6
Published
Kryptos Connect Mobile SDK for React Native - Simplifies Web3 finance for mobile apps with support for 5000+ DeFi protocols, 200+ exchanges and wallets, and 100+ blockchains. Works with both Expo and React Native CLI.
Readme
@kryptos_connect/mobile-sdk
Kryptos Connect Mobile SDK for React Native – works with Expo and React Native CLI. Seamless Kryptos integration with built-in authentication, theme support, and wallet connectivity. Connect your users to the complete Web3 finance ecosystem with support for 5000+ DeFi protocols, 200+ exchanges and wallets, and 100+ blockchains.
Installation
Using npm
npm install @kryptos_connect/mobile-sdk react-native-svgUsing yarn
yarn add @kryptos_connect/mobile-sdk react-native-svgFor Expo
npx expo install @kryptos_connect/mobile-sdk react-native-svgiOS (React Native CLI only)
cd ios && pod installPrerequisites
Before using this package, you'll need:
- Client ID: Obtain from Kryptos Developer Portal
- WalletConnect Project ID: Get from WalletConnect Cloud (optional, for wallet connectivity)
Core library (all-in-one)
For Expo or bare React Native, install the core WalletConnect/AppKit deps together:
npx expo install @reown/appkit-react-native @react-native-async-storage/async-storage react-native-get-random-values react-native-svg @react-native-community/netinfo @walletconnect/react-native-compat react-native-safe-area-context expo-applicationPlatform Setup
Expo (managed or prebuild)
Install the required peer deps (AppKit + WalletConnect) in one go:
npx expo install @kryptos_connect/mobile-sdk react-native-svg @react-native-async-storage/async-storage @react-native-community/netinfo react-native-get-random-values @walletconnect/react-native-compat @reown/appkit-react-native @reown/appkit-ethers-react-native expo-applicationExpo SDK 53+: add
babel.config.jsto enableunstable_transformImportMetaforvaltio:// babel.config.js module.exports = function (api) { api.cache(true); return { presets: [["babel-preset-expo", { unstable_transformImportMeta: true }]], }; };
React Native CLI
- Install peer deps:
npm install @kryptos_connect/mobile-sdk react-native-svg @react-native-async-storage/async-storage @react-native-community/netinfo react-native-get-random-values @walletconnect/react-native-compat @reown/appkit-react-native @reown/appkit-ethers-react-native viem - iOS:
cd ios && pod install.
Quick Start
1. Wrap your app with the Provider
import { KryptosConnectProvider } from "@kryptos_connect/mobile-sdk";
const config = {
appName: "Your App Name",
appLogo: "https://your-logo-url.com/logo.png", // or require('./logo.png')
clientId: "your-client-id",
theme: "light", // or 'dark'
walletConnectProjectId: "your-walletconnect-project-id",
};
export default function App() {
return (
<KryptosConnectProvider config={config}>
<YourApp />
</KryptosConnectProvider>
);
}Configuration Options
| Property | Type | Required | Description |
| ------------------------ | ------------------------------------------ | -------- | --------------------------------------------------------------------------- |
| appName | string | Yes | Your application name |
| appLogo | React.ReactNode \| string \| ImageSource | No | Your app logo (URL, require(), or React Native image source) |
| clientId | string | Yes | Your Kryptos client ID |
| theme | "light" \| "dark" | No | Default theme mode (defaults to "light" if not set) |
| walletConnectProjectId | string | No | Your WalletConnect project ID (enables built-in AppKit / wallet connection) |
2. Add the Connect Button
import { KryptosConnectButton } from "@kryptos_connect/mobile-sdk";
function YourComponent() {
const generateLinkToken = async () => {
// Call your backend API to generate a link token
const response = await fetch("https://your-api.com/generate-link-token", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
// Optional: Include access_token for authenticated users
// access_token: userAccessToken
}),
});
const data = await response.json();
// Return link_token and isAuthorized flag
return {
link_token: data.link_token,
isAuthorized: data.isAuthorized, // pass true if access_token was provided
};
};
const handleSuccess = (userConsent) => {
console.log("Connection successful!", userConsent);
// For new users, exchange the public token for an access token
// For authorized users, userConsent might be null
if (userConsent?.public_token) {
exchangePublicToken(userConsent.public_token);
}
};
const handleError = (error) => {
console.error("Connection failed:", error);
};
return (
<KryptosConnectButton
generateLinkToken={generateLinkToken}
onSuccess={handleSuccess}
onError={handleError}
/>
);
}User Flow Variations
The SDK automatically handles two different user flows based on the isAuthorized flag returned from generateLinkToken:
Flow 1: New User (isAuthorized: false or undefined)
INIT → Connect → INTEGRATION → STATUS- INIT (Connect): Fetches link token and initializes the session & an account is created for them on the backend
- INTEGRATION: User selects and connects integrations (wallets, exchanges, blockchains)
- STATUS: Success or error result; returns
public_tokeninonSuccesswhen consent is given, ornullwhen user was already authorized
Flow 2: Authenticated User (isAuthorized: true)
INIT → INTEGRATION → STATUS- Skips Connect (an account already exists for the user on the backend)
- User directly selects integrations
- Returns
nullinonSuccesscallback (no new token needed)
Implementation Example
const generateLinkToken = async () => {
const user = getCurrentUser(); // Your auth logic
const response = await fetch("/api/kryptos/create-link-token", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
// Include access_token if user is logged in
access_token: user?.kryptosAccessToken || undefined,
}),
});
const data = await response.json();
return {
link_token: data.link_token,
// isAuthorized will be true if access_token was valid
isAuthorized: !!user?.kryptosAccessToken,
};
};WalletConnect / Reown AppKit configuration
Passing a walletConnectProjectId to KryptosConnectProvider enables the built-in AppKit (WalletConnect v2) flow used by the WalletConnectComponent:
import "@walletconnect/react-native-compat";
import "react-native-get-random-values";
import { KryptosConnectProvider } from "@kryptos_connect/mobile-sdk";
const config = {
appName: "Your App",
appLogo: "https://your-logo.png",
clientId: "<kryptos-client-id>",
walletConnectProjectId: "<walletconnect-cloud-project-id>",
};
export default function App() {
return (
<KryptosConnectProvider config={config}>
<YourApp />
</KryptosConnectProvider>
);
}Behind the scenes the SDK creates an AppKit instance (see src/wallet-connect/AppKitConfig.ts) with Ethers adapter, common EVM chains, and persistent storage. If you need to customize chains, metadata, or features, copy that file into your app and adjust it following the Reown AppKit guide: https://docs.reown.com/appkit/overview
Environment Configuration
You can configure different environments (dev/prod) by passing the baseUrl option:
import { KryptosConnectProvider } from "@kryptos_connect/mobile-sdk";
// Development Environment
const devConfig = {
appName: "Your App",
clientId: "your-client-id",
theme: "light",
walletConnectProjectId: "your-project-id",
};
// Production Environment
const prodConfig = {
appName: "Your App",
clientId: "your-client-id",
theme: "light",
walletConnectProjectId: "your-project-id",
};
export default function App() {
const config = __DEV__ ? devConfig : prodConfig;
return (
<KryptosConnectProvider config={config}>
<YourApp />
</KryptosConnectProvider>
);
}3. Custom Button (Optional)
You can also use a custom button:
import { KryptosConnectButton } from "@kryptos_connect/mobile-sdk";
import { Text, View, StyleSheet } from "react-native";
function CustomButton() {
return (
<KryptosConnectButton
generateLinkToken={generateLinkToken}
onSuccess={handleSuccess}
onError={handleError}
>
<View style={styles.customButton}>
<Text style={styles.customText}>🔐 Connect Your Wallet</Text>
</View>
</KryptosConnectButton>
);
}
const styles = StyleSheet.create({
customButton: {
backgroundColor: "#00C693",
paddingVertical: 12,
paddingHorizontal: 24,
borderRadius: 8,
alignItems: "center",
},
customText: {
color: "#FFFFFF",
fontSize: 16,
fontWeight: "600",
},
});Direct Integration Flow
You can use the integrationName prop to direct users to a specific integration, bypassing the general integration selection. Useful for dedicated buttons for specific exchanges or wallets.
Getting supported integration IDs: Fetch from the public Kryptos API:
GET {BASE_URL}/integrations/public/listUsage example:
// Direct connection to a specific integration (e.g. Binance)
<KryptosConnectButton
generateLinkToken={generateLinkToken}
integrationName="binance"
onSuccess={(userConsent) => {
console.log("Binance connected:", userConsent);
}}
>
Connect Binance Account
</KryptosConnectButton>
// Default button text when integrationName is set: "Connect {Integration} Account"
<KryptosConnectButton
generateLinkToken={generateLinkToken}
integrationName="metamask"
onSuccess={(userConsent) => console.log("MetaMask connected:", userConsent)}
/>Use cases: Dedicated integration buttons, contextual integration (e.g. exchange-focused screens), onboarding steps (e.g. connect wallet then exchange). The integrationName value must match an integration ID from the supported providers list.
API Reference
KryptosConnectProvider
The provider component that wraps your app and provides the Kryptos context.
Props
| Prop | Type | Required | Description |
| ---------- | --------------- | -------- | -------------------- |
| config | KryptosConfig | Yes | Configuration object |
| children | ReactNode | Yes | Child components |
KryptosConfig
type KryptosConfig = {
appName: string; // Your app name
appLogo?: ReactNode | string | ImageSourcePropType; // Logo URL, React Native Image source, or require()
theme?: "light" | "dark"; // Theme mode (default: 'light')
clientId: string; // Your Kryptos client ID
walletConnectProjectId?: string; // Optional WalletConnect project ID
};KryptosConnectButton
The main button component that triggers the connection flow.
Props
| Prop | Type | Required | Description |
| ------------------- | --------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| generateLinkToken | () => Promise<{ link_token: string; isAuthorized?: boolean }> | Yes | Function that returns link token and authorization status. isAuthorized: true indicates the user is already authorized (consent API may be skipped; onSuccess receives null) |
| onSuccess | (data: UserConsent \| null) => void | No | Callback invoked when connection succeeds. Receives public_token for new users, null for authorized users |
| onError | (error?: Error) => void | No | Callback invoked when connection fails |
| integrationName | string | No | Integration ID from the supported providers list. When provided, skips the integration list and goes directly to that integration |
| children | ReactNode | No | Custom button content. Defaults to "Connect With Kryptos", or "Connect {Integration} Account" when integrationName is set |
| style | ViewStyle | No | Custom button container style |
| textStyle | TextStyle | No | Custom button text style |
TypeScript Types
interface KryptosConnectButtonProps {
generateLinkToken: () => Promise<{
link_token: string;
isAuthorized?: boolean;
}>;
onSuccess?: (data: UserConsent | null) => void;
onError?: (error?: Error) => void;
integrationName?: string; // Integration ID from the supported providers list
children?: ReactNode;
style?: ViewStyle;
textStyle?: TextStyle;
}
interface UserConsent {
public_token: string;
// Additional consent data
}
// Note: onSuccess receives:
// - UserConsent with public_token for new users (isAuthorized: false)
// - null for authenticated users (isAuthorized: true)TypeScript
The package includes type definitions. You can import types from the package:
import type {
KryptosConnectButtonProps,
KryptosConfig,
UserConsent,
} from "@kryptos_connect/mobile-sdk";Backend Integration
You need to implement two backend endpoints. The same API is used for web and mobile.
Base URLs
| Environment | URL |
| -------------- | -------------------------------- |
| Production | https://connect-api.kryptos.io |
1. Create Link Token
A link token can be created in two ways: to authenticate an existing user or to create a new session.
| Approach | When to use | | -------- | -------------------------------- | | Option A | New user, no access token | | Option B | Returning user, has access token |
Option A: Without Access Token (New/Anonymous User)
Use this approach for new users (no access token):
// Example: Node.js/Express
app.post("/api/kryptos/create-link-token", async (req, res) => {
try {
const response = await fetch(`${KRYPTOS_BASE_URL}/link-token`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Client-Id": YOUR_CLIENT_ID,
"X-Client-Secret": YOUR_CLIENT_SECRET,
},
body: JSON.stringify({
scopes:
"openid profile offline_access email portfolios:read transactions:read integrations:read tax:read accounting:read reports:read workspace:read users:read",
}),
});
const data = await response.json();
res.json({
link_token: data.link_token,
isAuthorized: false, // No access token provided
});
} catch (error) {
res.status(500).json({ error: "Failed to create link token" });
}
});User experience flow:
- User taps "Connect to Kryptos"
- Connect (INIT) screen initializes, then integration selection is shown
- User selects and connects integrations
onSuccessreceivespublic_tokento exchange
Option B: With Access Token (Authenticated User)
Use this approach for existing authenticated users:
// Example: Node.js/Express
app.post("/api/kryptos/create-link-token", async (req, res) => {
try {
// Get the user's stored access token from your database
const userAccessToken = await getUserAccessToken(req.user.id);
const response = await fetch(`${KRYPTOS_BASE_URL}/link-token`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Client-Id": YOUR_CLIENT_ID,
"X-Client-Secret": YOUR_CLIENT_SECRET,
},
body: JSON.stringify({
scopes:
"openid profile offline_access integrations:read integrations:write",
access_token: userAccessToken, // Pass the user's access token
}),
});
const data = await response.json();
res.json({
link_token: data.link_token,
isAuthorized: true, // Access token provided, user is authenticated
});
} catch (error) {
res.status(500).json({ error: "Failed to create link token" });
}
});User experience flow:
- User taps "Connect to Kryptos"
- Connect (INIT) then integration selection is shown
- User selects integrations;
onSuccessreceivesnull(no new token needed)
Choosing the Right Approach
| Scenario | Use Option | isAuthorized | User Flow (mobile) | Returns public_token |
| ------------------------------------------ | ----------------- | ------------ | -------------------------------------------------------------------------- | -------------------- |
| First-time user connecting to Kryptos | A (Without Token) | false | INIT → Connect(account created for user on backend) → INTEGRATION → STATUS | ✅ Yes |
| User doesn't have an access token yet | A (Without Token) | false | INIT → Connect(account created for user on backend) → INTEGRATION → STATUS | ✅ Yes |
| Returning user with stored access token | B (With Token) | true | INIT → INTEGRATION → STATUS | ❌ No |
| Adding more integrations for existing user | B (With Token) | true | INIT → INTEGRATION → STATUS | ❌ No |
Important notes:
- After the first successful connection (Option A), store the
access_tokenfrom the token exchange. - Use the stored
access_tokenfor subsequent connections (Option B). - For authorized users (
isAuthorized: true),onSuccessreceivesnull.
2. Exchange Public Token
After a successful connection, exchange the public_token for an access_token. Important: Store this access_token securely in your database. You will use it to create link tokens for authenticated users (Option B above).
// Example: Node.js/Express
app.post("/api/kryptos/exchange-token", async (req, res) => {
try {
const { public_token } = req.body;
const response = await fetch(`${KRYPTOS_BASE_URL}/token/exchange`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Client-Id": YOUR_CLIENT_ID,
"X-Client-Secret": YOUR_CLIENT_SECRET,
},
body: JSON.stringify({
public_token,
}),
});
const data = await response.json();
// IMPORTANT: Store the access_token securely in your database
// You'll need this token to:
// 1. Create authenticated link tokens (Option B)
// 2. Make API calls on behalf of the user
await saveUserAccessToken(req.user.id, data.access_token);
res.json({ success: true });
} catch (error) {
res.status(500).json({ error: "Failed to exchange token" });
}
});Complete integration flow:
First connection (new user –
isAuthorized: false):App → generateLinkToken() [returns { link_token, isAuthorized: false }] → SDK: INIT → Connect → INTEGRATION → STATUS → User selects and connects integrations → onSuccess receives { public_token } → Backend exchanges public_token for access_token → Store access_token in database ← IMPORTANTSubsequent connections (returning user –
isAuthorized: true):App → generateLinkToken() [returns { link_token, isAuthorized: true }] → SDK: INIT → INTEGRATION → STATUS → User sees integrations directly → connects more → onSuccess receives null → Integrations added to existing account
Supported Platforms
- ✅ iOS 12.0+
- ✅ Android 5.0+ (API 21+)
- ✅ Expo SDK 48+
- ✅ React Native 0.60+
Peer Dependencies
{
"react": ">=16.8.0",
"react-native": ">=0.60.0",
"react-native-svg": ">=12.0.0"
}Support
- 📧 Email: [email protected]
- 📚 Documentation: https://docs.kryptos.io
- 💬 Discord: Join our community
- 🐛 Issues: GitHub Issues
License
MIT © Kryptos
Made with ❤️ by the Kryptos team
