Skip to main content

Mobile SDK

The Kryptos Connect Mobile SDK provides React Native components for iOS and Android applications. It works with both Expo and React Native CLI.

Before you begin

Make sure you have completed the prerequisites in the overview and set up your backend server.

Installation

npm install @kryptos_connect/mobile-sdk react-native-webview

iOS (React Native CLI only):

cd ios && pod install

Prerequisites

Quick Start

import { KryptosConnect, KryptosConnectButton } from "@kryptos_connect/mobile-sdk";

// 1. Initialize once (or on every render to keep config in sync)
KryptosConnect.init({
clientId: "your-client-id",
appName: "My App",
appLogo: "https://yourapp.com/logo.png",
theme: "light", // "light" | "dark" | "auto"
language: "en",
authMethods: ["email", "anonymous"],
});

// 2. Drop in the button
<KryptosConnectButton
generateLinkToken={generateLinkToken}
onConnectSuccess={(consent) => console.log(consent.public_token)}
onConnectError={(err) => console.error(err)}
buttonLabel="Connect Kryptos"
buttonHeight={52}
/>;

Full Example

import { KryptosConnect, KryptosConnectButton } from "@kryptos_connect/mobile-sdk";
import { useState } from "react";

const BASE_URL = "https://connect-api.kryptos.io";
const CLIENT_ID = "your-client-id";
const CLIENT_SECRET = "your-client-secret"; // keep server-side in production
const SCOPES = "openid profile offline_access email portfolios:read integrations:read";

export default function App() {
const [accessToken, setAccessToken] = useState(null);

KryptosConnect.init({
clientId: CLIENT_ID,
appName: "My App",
theme: "light",
language: "en",
authMethods: ["email", "anonymous"],
});

async function generateLinkToken(existingAccessToken?: string | null) {
const body: Record<string, unknown> = { scopes: SCOPES };
if (existingAccessToken) body.access_token = existingAccessToken;

const res = await fetch(`${BASE_URL}/link-token`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Client-Id": CLIENT_ID,
"X-Client-Secret": CLIENT_SECRET,
},
body: JSON.stringify(body),
});
const data = await res.json();
return { link_token: data.data.link_token, isAuthorized: !!existingAccessToken };
}

async function handleSuccess(consent) {
if (!consent) return; // re-auth — no new token
const res = await fetch(`${BASE_URL}/token/exchange`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
public_token: consent.public_token,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
}),
});
const data = await res.json();
setAccessToken(data.data.access_token);
}

return (
<>
{/* Default button */}
<KryptosConnectButton
generateLinkToken={() => generateLinkToken()}
onConnectSuccess={handleSuccess}
onConnectError={(err) => console.error(err)}
buttonLabel="Link Kryptos Account"
buttonHeight={52}
/>

{/* Pre-select a specific integration with custom style */}
<KryptosConnectButton
generateLinkToken={() => generateLinkToken()}
onConnectSuccess={handleSuccess}
onConnectError={(err) => console.error(err)}
integrationName="coinbase"
buttonLabel="Connect Coinbase"
buttonHeight={48}
style={{ borderRadius: 10, backgroundColor: "#0052FF" }}
/>

{/* Re-authorize with stored access token */}
{accessToken && (
<KryptosConnectButton
generateLinkToken={() => generateLinkToken(accessToken)}
onConnectSuccess={handleSuccess}
onConnectError={(err) => console.error(err)}
buttonLabel="Continue with Access Token"
buttonHeight={52}
/>
)}
</>
);
}

User Flow Variations

The SDK handles two flows based on the isAuthorized flag returned from generateLinkToken:

Flow 1: New User (isAuthorized: false or undefined)

press → AUTH → INTEGRATION → onConnectSuccess({ public_token })

Exchange public_token server-side for a long-lived access_token.

Flow 2: Returning User (isAuthorized: true)

press → INTEGRATION → onConnectSuccess(null)

Pass stored access_token in the link-token request body and return isAuthorized: true. No new token is issued.

KryptosConnect.init Config

KeyTypeRequiredDescription
clientIdstringYesYour Kryptos client ID.
appNamestringYesDisplayed in the connect UI header.
appLogostringNoURI to your app logo shown in the connect UI.
walletConnectProjectIdstringNoRequired if using WalletConnect.
theme"light" | "dark" | "auto"NoUI theme. Default "light".
languagestringNoUI language. Supported: en fr de pt sv es pl it.
authMethods("email" | "anonymous")[]NoAuth methods shown. Default: both.
cssVarsRecord<string, string>NoOverride --kc-* CSS variables in the connect UI. --kc-primary and --kc-primary-text also apply to the native button.

Restricting Auth Methods

// Email only
KryptosConnect.init({
clientId: "your-client-id",
appName: "My App",
authMethods: ["email"],
});

// Anonymous only
KryptosConnect.init({
clientId: "your-client-id",
appName: "My App",
authMethods: ["anonymous"],
});

Setting the Language

CodeLanguage
"en"English
"fr"French
"de"German
"pt"Portuguese
"sv"Swedish
"es"Spanish
"pl"Polish
"it"Italian

KryptosConnectButton Props

PropTypeRequiredDescription
generateLinkToken() => Promise<{ link_token: string; isAuthorized?: boolean }>YesCalled on press. Return isAuthorized: true to skip auth for existing users.
onConnectSuccess(data: UserConsent | null) => voidYesCalled on success. data is null when isAuthorized was true.
onConnectError(error: Error) => voidYesCalled on error or dismissal.
integrationNamestringNoSkip the integration list and open a specific integration directly.
buttonLabelstringNoButton text.
buttonHeightnumberNoButton height in dp. Default 56.
extraConfigRecord<string, unknown>NoPer-button config overrides merged onto the global config. Pass prefill here to pre-populate integration form fields.
styleStyleProp<ViewStyle>NoStyle for the button. backgroundColor overrides --kc-primary for that button.

Pre-filling Integration Forms

Pass a prefill object inside extraConfig to pre-populate the integration form when the user reaches the connection step. All fields are optional — pass only the ones you have.

FieldTypeDescription
prefill.addressstringWallet or blockchain address. Triggers chain auto-detect for EVM wallets.
prefill.apiKeystringAPI key for exchange or API-based integrations.
prefill.secretKeystringSecret key for integrations that require one.
prefill.passwordstringPassword for integrations that require one.
prefill.accountNamestringAccount name for account-based integrations.
// Pre-fill a wallet address — chains are auto-detected
<KryptosConnectButton
generateLinkToken={generateLinkToken}
onConnectSuccess={handleSuccess}
onConnectError={(err) => console.error(err)}
integrationName="ethereum"
buttonLabel="Connect Wallet"
extraConfig={{ prefill: { address: "0x1234567890123456789012345678901234567890" } }}
/>

// Pre-fill API credentials for an exchange
<KryptosConnectButton
generateLinkToken={generateLinkToken}
onConnectSuccess={handleSuccess}
onConnectError={(err) => console.error(err)}
integrationName="binance"
buttonLabel="Connect Binance"
extraConfig={{ prefill: { apiKey: "user-api-key", secretKey: "user-secret-key" } }}
/>
info

Prefilled values populate the form as editable defaults — the user can still change them before submitting. For EVM wallets, providing an address automatically triggers chain detection and pre-selects all detected chains.

Theming & Customization

Theme the connect UI by passing cssVars to KryptosConnect.init. The connect UI runs inside a WebView, so global stylesheet overrides have no effect. --kc-primary and --kc-primary-text also apply to the native button's background and label.

KryptosConnect.init({
clientId: "your-client-id",
appName: "My App",
cssVars: {
"--kc-primary": "#6366f1",
"--kc-primary-hover": "#4f46e5",
"--kc-primary-text": "#ffffff",
"--kc-border-focus": "#6366f1",
},
});

For per-button overrides, use the style prop. backgroundColor takes precedence over --kc-primary for that button only:

<KryptosConnectButton
generateLinkToken={generateLinkToken}
onConnectSuccess={handleSuccess}
onConnectError={(err) => console.error(err)}
buttonLabel="Connect Coinbase"
buttonHeight={48}
style={{ backgroundColor: "#0052FF", borderRadius: 10 }}
/>

For the complete variable reference, see Theming & Customization.

Direct Integration Flow

The integrationName prop directs users to a specific integration, bypassing the integration selection page.

Fetch available integration IDs from the public Kryptos API (see Public Endpoints - Integrations).

<KryptosConnectButton
generateLinkToken={generateLinkToken}
onConnectSuccess={handleSuccess}
onConnectError={(err) => console.error(err)}
integrationName="binance"
buttonLabel="Connect Binance"
/>
info

The integrationName value must match an integration ID from the supported providers list.

Platform Requirements

PlatformMinimum Version
iOS12.0+
AndroidAPI 21+ (Android 5.0+)
React Native0.60+
Expo SDK48+

Features

  • Cross-Platform: Single codebase for iOS and Android
  • Expo Support: Works with Expo and React Native CLI
  • WalletConnect v2: Built-in WalletConnect integration
  • Theming: Light, dark, and auto theme support with CSS variable customization
  • TypeScript: Full TypeScript support

Next steps