@kryptos_connect/mobile-sdk 1.0.6-dev.1 → 2.0.1-dev.0

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 CHANGED
@@ -1,625 +1,249 @@
1
1
  # @kryptos_connect/mobile-sdk
2
2
 
3
- 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.
3
+ 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.
4
4
 
5
5
  ## Installation
6
6
 
7
- ### Using npm
8
-
9
- ```bash
10
- npm install @kryptos_connect/mobile-sdk react-native-svg
11
- ```
12
-
13
- ### Using yarn
14
-
15
7
  ```bash
16
- yarn add @kryptos_connect/mobile-sdk react-native-svg
8
+ npm install @kryptos_connect/mobile-sdk react-native-webview
17
9
  ```
18
10
 
19
- ### For Expo
20
-
21
- ```bash
22
- npx expo install @kryptos_connect/mobile-sdk react-native-svg
23
- ```
24
-
25
- ### iOS (React Native CLI only)
26
-
27
11
  ```bash
12
+ # iOS — install native pods
28
13
  cd ios && pod install
29
14
  ```
30
15
 
31
16
  ## Prerequisites
32
17
 
33
- Before using this package, you'll need:
34
-
35
- 1. **Client ID**: Obtain from [Kryptos Developer Portal](https://dashboard.kryptos.io)
36
- 2. **WalletConnect Project ID**: Get from [WalletConnect Cloud](https://cloud.walletconnect.com) (optional, for wallet connectivity)
18
+ - **Client ID** from the [Kryptos Developer Portal](https://dashboard.kryptos.io/)
19
+ - **WalletConnect Project ID** — from [WalletConnect Cloud](https://cloud.walletconnect.com) _(optional)_
37
20
 
38
- ## Core library (all-in-one)
39
-
40
- For Expo or bare React Native, install the core WalletConnect/AppKit deps together:
41
-
42
- ```bash
43
- 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-application
44
- ```
45
-
46
- ## Platform Setup
47
-
48
- ### Expo (managed or prebuild)
49
-
50
- - Install the required peer deps (AppKit + WalletConnect) in one go:
21
+ ---
51
22
 
52
- ```bash
53
- 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-application
54
- ```
23
+ ## Quick start
55
24
 
56
- - Expo SDK 53+: add `babel.config.js` to enable `unstable_transformImportMeta` for `valtio`:
57
- ```js
58
- // babel.config.js
59
- module.exports = function (api) {
60
- api.cache(true);
61
- return {
62
- presets: [["babel-preset-expo", { unstable_transformImportMeta: true }]],
63
- };
64
- };
65
- ```
25
+ ```tsx
26
+ import { KryptosConnect, KryptosConnectButton } from "@kryptos_connect/mobile-sdk";
66
27
 
67
- ### React Native CLI
28
+ // 1. Initialize once (or on every render to keep config in sync)
29
+ KryptosConnect.init({
30
+ clientId: "your-client-id",
31
+ appName: "My App",
32
+ appLogo: "https://yourapp.com/logo.png",
33
+ baseUrl: "https://connect-api.kryptos.io",
34
+ theme: "light", // "light" | "dark" | "auto"
35
+ language: "en", // "en" | "fr" | "de" | "pt" | "sv" | "es" | "pl" | "it"
36
+ authMethods: ["email", "anonymous"],
37
+ });
68
38
 
69
- - Install peer deps:
70
- ```bash
71
- 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
72
- ```
73
- - iOS: `cd ios && pod install`.
39
+ // 2. Drop in the button
40
+ <KryptosConnectButton
41
+ generateLinkToken={generateLinkToken}
42
+ onConnectSuccess={(consent) => console.log(consent.public_token)}
43
+ onConnectError={(err) => console.error(err)}
44
+ buttonLabel="Connect Kryptos"
45
+ buttonHeight={52}
46
+ />;
47
+ ```
74
48
 
75
- ## Quick Start
49
+ ---
76
50
 
77
- ### 1. Wrap your app with the Provider
51
+ ## Full example
78
52
 
79
53
  ```tsx
80
- import { KryptosConnectProvider } from "@kryptos_connect/mobile-sdk";
54
+ import { KryptosConnect, KryptosConnectButton } from "@kryptos_connect/mobile-sdk";
55
+ import { useState } from "react";
81
56
 
82
- const config = {
83
- appName: "Your App Name",
84
- appLogo: "https://your-logo-url.com/logo.png", // or require('./logo.png')
85
- clientId: "your-client-id",
86
- theme: "light", // or 'dark'
87
- walletConnectProjectId: "your-walletconnect-project-id",
88
- };
57
+ const BASE_URL = "https://connect-api.kryptos.io";
58
+ const CLIENT_ID = "your-client-id";
59
+ const CLIENT_SECRET = "your-client-secret"; // keep server-side in production
60
+ const SCOPES = "openid profile offline_access email portfolios:read integrations:read";
89
61
 
90
62
  export default function App() {
91
- return (
92
- <KryptosConnectProvider config={config}>
93
- <YourApp />
94
- </KryptosConnectProvider>
95
- );
96
- }
97
- ```
98
-
99
- ### Configuration Options
100
-
101
- | Property | Type | Required | Description |
102
- | ------------------------ | ------------------------------------------ | -------- | --------------------------------------------------------------------------- |
103
- | `appName` | `string` | Yes | Your application name |
104
- | `appLogo` | `React.ReactNode \| string \| ImageSource` | No | Your app logo (URL, `require()`, or React Native image source) |
105
- | `clientId` | `string` | Yes | Your Kryptos client ID |
106
- | `theme` | `"light" \| "dark"` | No | Default theme mode (defaults to `"light"` if not set) |
107
- | `walletConnectProjectId` | `string` | No | Your WalletConnect project ID (enables built-in AppKit / wallet connection) |
108
-
109
- ### 2. Add the Connect Button
63
+ const [accessToken, setAccessToken] = useState(null);
64
+
65
+ KryptosConnect.init({
66
+ clientId: CLIENT_ID,
67
+ appName: "My App",
68
+ baseUrl: BASE_URL,
69
+ theme: "light",
70
+ language: "en",
71
+ authMethods: ["email", "anonymous"],
72
+ });
110
73
 
111
- ```tsx
112
- import { KryptosConnectButton } from "@kryptos_connect/mobile-sdk";
74
+ async function generateLinkToken(existingAccessToken?: string | null) {
75
+ const body: Record<string, unknown> = { scopes: SCOPES };
76
+ if (existingAccessToken) body.access_token = existingAccessToken;
113
77
 
114
- function YourComponent() {
115
- const generateLinkToken = async () => {
116
- // Call your backend API to generate a link token
117
- const response = await fetch("https://your-api.com/generate-link-token", {
78
+ const res = await fetch(`${BASE_URL}/link-token`, {
118
79
  method: "POST",
119
80
  headers: {
120
81
  "Content-Type": "application/json",
82
+ "X-Client-Id": CLIENT_ID,
83
+ "X-Client-Secret": CLIENT_SECRET,
121
84
  },
85
+ body: JSON.stringify(body),
86
+ });
87
+ const data = await res.json();
88
+ return { link_token: data.data.link_token, isAuthorized: !!existingAccessToken };
89
+ }
90
+
91
+ async function handleSuccess(consent) {
92
+ if (!consent) return; // re-auth — no new token
93
+ const res = await fetch(`${BASE_URL}/token/exchange`, {
94
+ method: "POST",
95
+ headers: { "Content-Type": "application/json" },
122
96
  body: JSON.stringify({
123
- // Optional: Include access_token for authenticated users
124
- // access_token: userAccessToken
97
+ public_token: consent.public_token,
98
+ client_id: CLIENT_ID,
99
+ client_secret: CLIENT_SECRET,
125
100
  }),
126
101
  });
127
- const data = await response.json();
128
- // Return link_token and isAuthorized flag
129
- return {
130
- link_token: data.link_token,
131
- isAuthorized: data.isAuthorized, // pass true if access_token was provided
132
- };
133
- };
134
-
135
- const handleSuccess = (userConsent) => {
136
- console.log("Connection successful!", userConsent);
137
- // For new users, exchange the public token for an access token
138
- // For authorized users, userConsent might be null
139
- if (userConsent?.public_token) {
140
- exchangePublicToken(userConsent.public_token);
141
- }
142
- };
143
-
144
- const handleError = (error) => {
145
- console.error("Connection failed:", error);
146
- };
147
-
148
- return (
149
- <KryptosConnectButton
150
- generateLinkToken={generateLinkToken}
151
- onSuccess={handleSuccess}
152
- onError={handleError}
153
- />
154
- );
155
- }
156
- ```
157
-
158
- #### User Flow Variations
159
-
160
- The SDK automatically handles two different user flows based on the `isAuthorized` flag returned from `generateLinkToken`:
161
-
162
- **Flow 1: New User** (`isAuthorized: false` or undefined)
163
-
164
- ```
165
- INIT → Connect → INTEGRATION → STATUS
166
- ```
167
-
168
- - **INIT (Connect)**: Fetches link token and initializes the session & an account is created for them on the backend
169
- - **INTEGRATION**: User selects and connects integrations (wallets, exchanges, blockchains)
170
- - **STATUS**: Success or error result; returns `public_token` in `onSuccess` when consent is given, or `null` when user was already authorized
171
-
172
- **Flow 2: Authenticated User** (`isAuthorized: true`)
173
-
174
- ```
175
- INIT → INTEGRATION → STATUS
176
- ```
177
-
178
- - Skips Connect (an account already exists for the user on the backend)
179
- - User directly selects integrations
180
- - Returns `null` in `onSuccess` callback (no new token needed)
181
-
182
- ### Implementation Example
183
-
184
- ```tsx
185
- const generateLinkToken = async () => {
186
- const user = getCurrentUser(); // Your auth logic
187
-
188
- const response = await fetch("/api/kryptos/create-link-token", {
189
- method: "POST",
190
- headers: {
191
- "Content-Type": "application/json",
192
- },
193
- body: JSON.stringify({
194
- // Include access_token if user is logged in
195
- access_token: user?.kryptosAccessToken || undefined,
196
- }),
197
- });
198
-
199
- const data = await response.json();
200
-
201
- return {
202
- link_token: data.link_token,
203
- // isAuthorized will be true if access_token was valid
204
- isAuthorized: !!user?.kryptosAccessToken,
205
- };
206
- };
207
- ```
208
-
209
- ## WalletConnect / Reown AppKit configuration
210
-
211
- Passing a `walletConnectProjectId` to `KryptosConnectProvider` enables the built-in AppKit (WalletConnect v2) flow used by the `WalletConnectComponent`:
212
-
213
- ```tsx
214
- import "@walletconnect/react-native-compat";
215
- import "react-native-get-random-values";
216
- import { KryptosConnectProvider } from "@kryptos_connect/mobile-sdk";
217
-
218
- const config = {
219
- appName: "Your App",
220
- appLogo: "https://your-logo.png",
221
- clientId: "<kryptos-client-id>",
222
- walletConnectProjectId: "<walletconnect-cloud-project-id>",
223
- };
102
+ const data = await res.json();
103
+ setAccessToken(data.data.access_token);
104
+ }
224
105
 
225
- export default function App() {
226
106
  return (
227
- <KryptosConnectProvider config={config}>
228
- <YourApp />
229
- </KryptosConnectProvider>
107
+ <>
108
+ {/* Default button */}
109
+ <KryptosConnectButton
110
+ generateLinkToken={() => generateLinkToken()}
111
+ onConnectSuccess={handleSuccess}
112
+ onConnectError={(err) => console.error(err)}
113
+ buttonLabel="Link Kryptos Account"
114
+ buttonHeight={52}
115
+ />
116
+
117
+ {/* Pre-select a specific integration with custom style */}
118
+ <KryptosConnectButton
119
+ generateLinkToken={() => generateLinkToken()}
120
+ onConnectSuccess={handleSuccess}
121
+ onConnectError={(err) => console.error(err)}
122
+ integrationName="coinbase"
123
+ buttonLabel="Connect Coinbase"
124
+ buttonHeight={48}
125
+ style={{ borderRadius: 10, backgroundColor: "#0052FF" }}
126
+ />
127
+
128
+ {/* Re-authorize with stored access token */}
129
+ {accessToken && (
130
+ <KryptosConnectButton
131
+ generateLinkToken={() => generateLinkToken(accessToken)}
132
+ onConnectSuccess={handleSuccess}
133
+ onConnectError={(err) => console.error(err)}
134
+ buttonLabel="Continue with Access Token"
135
+ buttonHeight={52}
136
+ />
137
+ )}
138
+ </>
230
139
  );
231
140
  }
232
141
  ```
233
142
 
234
- 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
143
+ ---
235
144
 
236
- ### Environment Configuration
145
+ ## KryptosConnectButton props
237
146
 
238
- You can configure different environments (dev/prod) by passing the `baseUrl` option:
147
+ | Prop | Type | Required | Description |
148
+ | ------------------- | --------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------- |
149
+ | `generateLinkToken` | `() => Promise<{ link_token: string; isAuthorized?: boolean }>` | Yes | Called on press. Return `isAuthorized: true` to skip auth for existing users. |
150
+ | `onConnectSuccess` | `(data: UserConsent \| null) => void` | Yes | Called on success. `data` is `null` when `isAuthorized` was `true`. |
151
+ | `onConnectError` | `(error: Error) => void` | Yes | Called on error or dismissal. |
152
+ | `integrationName` | `string` | No | Skip the integration list and open a specific integration directly. |
153
+ | `buttonLabel` | `string` | No | Button text. |
154
+ | `buttonHeight` | `number` | No | Button height in dp. Default `56`. |
155
+ | `extraConfig` | `Record<string, unknown>` | No | Per-button config overrides, merged onto the global config. |
156
+ | `style` | `StyleProp<ViewStyle>` | No | Style for the button. `backgroundColor` overrides `--kc-primary` for that button. |
239
157
 
240
- ```tsx
241
- import { KryptosConnectProvider } from "@kryptos_connect/mobile-sdk";
242
-
243
- // Development Environment
244
- const devConfig = {
245
- appName: "Your App",
246
- clientId: "your-client-id",
247
- theme: "light",
248
- walletConnectProjectId: "your-project-id",
249
- };
158
+ ---
250
159
 
251
- // Production Environment
252
- const prodConfig = {
253
- appName: "Your App",
254
- clientId: "your-client-id",
255
- theme: "light",
256
- walletConnectProjectId: "your-project-id",
257
- };
160
+ ## KryptosConnect.init config
258
161
 
259
- export default function App() {
260
- const config = __DEV__ ? devConfig : prodConfig;
162
+ | Key | Type | Required | Description |
163
+ | ------------------------ | ----------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- |
164
+ | `appName` | `string` | Yes | Displayed in the connect UI header. |
165
+ | `clientId` | `string` | No | Your Kryptos client ID. |
166
+ | `appLogo` | `string` | No | URI to your app logo shown in the connect UI. |
167
+ | `walletConnectProjectId` | `string` | No | Required if using WalletConnect. |
168
+ | `theme` | `"light" \| "dark" \| "auto"` | No | UI theme. Default `"light"`. |
169
+ | `language` | `string` | No | UI language. Supported: `en fr de pt sv es pl it`. |
170
+ | `authMethods` | `("email" \| "anonymous")[]` | No | Auth methods shown. Default: both. |
171
+ | `cssVars` | `Record<string, string>` | No | Override `--kc-*` CSS variables in the connect UI. `--kc-primary` and `--kc-primary-text` also apply to the native button. |
261
172
 
262
- return (
263
- <KryptosConnectProvider config={config}>
264
- <YourApp />
265
- </KryptosConnectProvider>
266
- );
267
- }
268
- ```
173
+ ---
269
174
 
270
- ### 3. Custom Button (Optional)
175
+ ## Customization
271
176
 
272
- You can also use a custom button:
177
+ Pass `cssVars` to theme the connect UI and native button colors:
273
178
 
274
179
  ```tsx
275
- import { KryptosConnectButton } from "@kryptos_connect/mobile-sdk";
276
- import { Text, View, StyleSheet } from "react-native";
277
-
278
- function CustomButton() {
279
- return (
280
- <KryptosConnectButton
281
- generateLinkToken={generateLinkToken}
282
- onSuccess={handleSuccess}
283
- onError={handleError}
284
- >
285
- <View style={styles.customButton}>
286
- <Text style={styles.customText}>🔐 Connect Your Wallet</Text>
287
- </View>
288
- </KryptosConnectButton>
289
- );
290
- }
291
-
292
- const styles = StyleSheet.create({
293
- customButton: {
294
- backgroundColor: "#00C693",
295
- paddingVertical: 12,
296
- paddingHorizontal: 24,
297
- borderRadius: 8,
298
- alignItems: "center",
299
- },
300
- customText: {
301
- color: "#FFFFFF",
302
- fontSize: 16,
303
- fontWeight: "600",
180
+ KryptosConnect.init({
181
+ cssVars: {
182
+ "--kc-primary": "#8b5cf6",
183
+ "--kc-primary-hover": "#7c3aed",
184
+ "--kc-primary-text": "#ffffff",
185
+ "--kc-primary-light": "#ede9fe",
304
186
  },
305
187
  });
306
188
  ```
307
189
 
308
- #### Direct Integration Flow
309
-
310
- 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.
311
-
312
- **Getting supported integration IDs:** Fetch from the public Kryptos API:
313
-
314
- ```bash
315
- GET {BASE_URL}/integrations/public/list
316
- ```
317
-
318
- **Usage example:**
190
+ To override colors on a per-button basis, use the `style` prop:
319
191
 
320
192
  ```tsx
321
- // Direct connection to a specific integration (e.g. Binance)
322
- <KryptosConnectButton
323
- generateLinkToken={generateLinkToken}
324
- integrationName="binance"
325
- onSuccess={(userConsent) => {
326
- console.log("Binance connected:", userConsent);
327
- }}
328
- >
329
- Connect Binance Account
330
- </KryptosConnectButton>
331
-
332
- // Default button text when integrationName is set: "Connect {Integration} Account"
333
193
  <KryptosConnectButton
334
- generateLinkToken={generateLinkToken}
335
- integrationName="metamask"
336
- onSuccess={(userConsent) => console.log("MetaMask connected:", userConsent)}
194
+ style={{ backgroundColor: "#0052FF", borderRadius: 10 }}
195
+ ...
337
196
  />
338
197
  ```
339
198
 
340
- **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.
341
-
342
- ## API Reference
343
-
344
- ### KryptosConnectProvider
345
-
346
- The provider component that wraps your app and provides the Kryptos context.
347
-
348
- #### Props
199
+ ---
349
200
 
350
- | Prop | Type | Required | Description |
351
- | ---------- | --------------- | -------- | -------------------- |
352
- | `config` | `KryptosConfig` | Yes | Configuration object |
353
- | `children` | `ReactNode` | Yes | Child components |
201
+ ## User flows
354
202
 
355
- #### KryptosConfig
203
+ **New user** — `generateLinkToken` returns `isAuthorized: false` (default):
356
204
 
357
- ```typescript
358
- type KryptosConfig = {
359
- appName: string; // Your app name
360
- appLogo?: ReactNode | string | ImageSourcePropType; // Logo URL, React Native Image source, or require()
361
- theme?: "light" | "dark"; // Theme mode (default: 'light')
362
- clientId: string; // Your Kryptos client ID
363
- walletConnectProjectId?: string; // Optional WalletConnect project ID
364
- };
365
205
  ```
366
-
367
- ### KryptosConnectButton
368
-
369
- The main button component that triggers the connection flow.
370
-
371
- #### Props
372
-
373
- | Prop | Type | Required | Description |
374
- | ------------------- | --------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
375
- | `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`) |
376
- | `onSuccess` | `(data: UserConsent \| null) => void` | No | Callback invoked when connection succeeds. Receives `public_token` for new users, `null` for authorized users |
377
- | `onError` | `(error?: Error) => void` | No | Callback invoked when connection fails |
378
- | `integrationName` | `string` | No | Integration ID from the supported providers list. When provided, skips the integration list and goes directly to that integration |
379
- | `children` | `ReactNode` | No | Custom button content. Defaults to "Connect With Kryptos", or "Connect {Integration} Account" when `integrationName` is set |
380
- | `style` | `ViewStyle` | No | Custom button container style |
381
- | `textStyle` | `TextStyle` | No | Custom button text style |
382
-
383
- #### TypeScript Types
384
-
385
- ```typescript
386
- interface KryptosConnectButtonProps {
387
- generateLinkToken: () => Promise<{
388
- link_token: string;
389
- isAuthorized?: boolean;
390
- }>;
391
- onSuccess?: (data: UserConsent | null) => void;
392
- onError?: (error?: Error) => void;
393
- integrationName?: string; // Integration ID from the supported providers list
394
- children?: ReactNode;
395
- style?: ViewStyle;
396
- textStyle?: TextStyle;
397
- }
398
-
399
- interface UserConsent {
400
- public_token: string;
401
- // Additional consent data
402
- }
403
-
404
- // Note: onSuccess receives:
405
- // - UserConsent with public_token for new users (isAuthorized: false)
406
- // - null for authenticated users (isAuthorized: true)
206
+ press → AUTH → INTEGRATION → onConnectSuccess({ public_token })
407
207
  ```
408
208
 
409
- ### TypeScript
209
+ Exchange `public_token` server-side for a long-lived `access_token`.
410
210
 
411
- The package includes type definitions. You can import types from the package:
211
+ **Returning user** pass stored `access_token` in the link-token request body and return `isAuthorized: true`:
412
212
 
413
- ```typescript
414
- import type {
415
- KryptosConnectButtonProps,
416
- KryptosConfig,
417
- UserConsent,
418
- } from "@kryptos_connect/mobile-sdk";
419
213
  ```
420
-
421
- ## Backend Integration
422
-
423
- You need to implement two backend endpoints. The same API is used for web and mobile.
424
-
425
- ### Base URLs
426
-
427
- | Environment | URL |
428
- | -------------- | -------------------------------- |
429
- | **Production** | `https://connect-api.kryptos.io` |
430
-
431
- ### 1. Create Link Token
432
-
433
- A link token can be created in two ways: to authenticate an existing user or to create a new session.
434
-
435
- | Approach | When to use |
436
- | -------- | -------------------------------- |
437
- | Option A | New user, no access token |
438
- | Option B | Returning user, has access token |
439
-
440
- #### Option A: Without Access Token (New/Anonymous User)
441
-
442
- Use this approach for **new users** (no access token):
443
-
444
- ```javascript
445
- // Example: Node.js/Express
446
- app.post("/api/kryptos/create-link-token", async (req, res) => {
447
- try {
448
- const response = await fetch(`${KRYPTOS_BASE_URL}/link-token`, {
449
- method: "POST",
450
- headers: {
451
- "Content-Type": "application/json",
452
- "X-Client-Id": YOUR_CLIENT_ID,
453
- "X-Client-Secret": YOUR_CLIENT_SECRET,
454
- },
455
- body: JSON.stringify({
456
- scopes:
457
- "openid profile offline_access email portfolios:read transactions:read integrations:read tax:read accounting:read reports:read workspace:read users:read",
458
- }),
459
- });
460
-
461
- const data = await response.json();
462
- res.json({
463
- link_token: data.link_token,
464
- isAuthorized: false, // No access token provided
465
- });
466
- } catch (error) {
467
- res.status(500).json({ error: "Failed to create link token" });
468
- }
469
- });
214
+ press → INTEGRATION → onConnectSuccess(null)
470
215
  ```
471
216
 
472
- **User experience flow:**
473
-
474
- 1. User taps "Connect to Kryptos"
475
- 2. Connect (INIT) screen initializes, then integration selection is shown
476
- 3. User selects and connects integrations
477
- 4. `onSuccess` receives `public_token` to exchange
478
-
479
- #### Option B: With Access Token (Authenticated User)
217
+ ---
480
218
 
481
- Use this approach for **existing authenticated users**:
219
+ ## Backend endpoints
482
220
 
483
- ```javascript
484
- // Example: Node.js/Express
485
- app.post("/api/kryptos/create-link-token", async (req, res) => {
486
- try {
487
- // Get the user's stored access token from your database
488
- const userAccessToken = await getUserAccessToken(req.user.id);
221
+ ### POST /link-token
489
222
 
490
- const response = await fetch(`${KRYPTOS_BASE_URL}/link-token`, {
491
- method: "POST",
492
- headers: {
493
- "Content-Type": "application/json",
494
- "X-Client-Id": YOUR_CLIENT_ID,
495
- "X-Client-Secret": YOUR_CLIENT_SECRET,
496
- },
497
- body: JSON.stringify({
498
- scopes:
499
- "openid profile offline_access integrations:read integrations:write",
500
- access_token: userAccessToken, // Pass the user's access token
501
- }),
502
- });
503
-
504
- const data = await response.json();
505
- res.json({
506
- link_token: data.link_token,
507
- isAuthorized: true, // Access token provided, user is authenticated
508
- });
509
- } catch (error) {
510
- res.status(500).json({ error: "Failed to create link token" });
511
- }
512
- });
223
+ ```
224
+ Headers: X-Client-Id, X-Client-Secret
225
+ Body: { scopes, access_token? }
226
+ Returns: { data: { link_token } }
513
227
  ```
514
228
 
515
- **User experience flow:**
516
-
517
- 1. User taps "Connect to Kryptos"
518
- 2. Connect (INIT) then integration selection is shown
519
- 3. User selects integrations; `onSuccess` receives `null` (no new token needed)
520
-
521
- #### Choosing the Right Approach
522
-
523
- | Scenario | Use Option | isAuthorized | User Flow (mobile) | Returns public_token |
524
- | ------------------------------------------ | ----------------- | ------------ | -------------------------------------------------------------------------- | -------------------- |
525
- | First-time user connecting to Kryptos | A (Without Token) | `false` | INIT → Connect(account created for user on backend) → INTEGRATION → STATUS | ✅ Yes |
526
- | User doesn't have an access token yet | A (Without Token) | `false` | INIT → Connect(account created for user on backend) → INTEGRATION → STATUS | ✅ Yes |
527
- | Returning user with stored access token | B (With Token) | `true` | INIT → INTEGRATION → STATUS | ❌ No |
528
- | Adding more integrations for existing user | B (With Token) | `true` | INIT → INTEGRATION → STATUS | ❌ No |
529
-
530
- **Important notes:**
531
-
532
- - After the first successful connection (Option A), store the `access_token` from the token exchange.
533
- - Use the stored `access_token` for subsequent connections (Option B).
534
- - For authorized users (`isAuthorized: true`), `onSuccess` receives `null`.
535
-
536
- ### 2. Exchange Public Token
537
-
538
- 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).
539
-
540
- ```javascript
541
- // Example: Node.js/Express
542
- app.post("/api/kryptos/exchange-token", async (req, res) => {
543
- try {
544
- const { public_token } = req.body;
545
-
546
- const response = await fetch(`${KRYPTOS_BASE_URL}/token/exchange`, {
547
- method: "POST",
548
- headers: {
549
- "Content-Type": "application/json",
550
- "X-Client-Id": YOUR_CLIENT_ID,
551
- "X-Client-Secret": YOUR_CLIENT_SECRET,
552
- },
553
- body: JSON.stringify({
554
- public_token,
555
- }),
556
- });
557
-
558
- const data = await response.json();
559
-
560
- // IMPORTANT: Store the access_token securely in your database
561
- // You'll need this token to:
562
- // 1. Create authenticated link tokens (Option B)
563
- // 2. Make API calls on behalf of the user
564
- await saveUserAccessToken(req.user.id, data.access_token);
229
+ ### POST /token/exchange
565
230
 
566
- res.json({ success: true });
567
- } catch (error) {
568
- res.status(500).json({ error: "Failed to exchange token" });
569
- }
570
- });
571
231
  ```
572
-
573
- **Complete integration flow:**
574
-
575
- 1. **First connection** (new user – `isAuthorized: false`):
576
-
577
- ```
578
- App → generateLinkToken() [returns { link_token, isAuthorized: false }]
579
- → SDK: INIT → Connect → INTEGRATION → STATUS
580
- → User selects and connects integrations
581
- → onSuccess receives { public_token }
582
- → Backend exchanges public_token for access_token
583
- → Store access_token in database ← IMPORTANT
584
- ```
585
-
586
- 2. **Subsequent connections** (returning user – `isAuthorized: true`):
587
- ```
588
- App → generateLinkToken() [returns { link_token, isAuthorized: true }]
589
- → SDK: INIT → INTEGRATION → STATUS
590
- → User sees integrations directly → connects more
591
- → onSuccess receives null
592
- → Integrations added to existing account
593
- ```
594
-
595
- ## Supported Platforms
596
-
597
- - ✅ iOS 12.0+
598
- - ✅ Android 5.0+ (API 21+)
599
- - ✅ Expo SDK 48+
600
- - ✅ React Native 0.60+
601
-
602
- ## Peer Dependencies
603
-
604
- ```json
605
- {
606
- "react": ">=16.8.0",
607
- "react-native": ">=0.60.0",
608
- "react-native-svg": ">=12.0.0"
609
- }
232
+ Body: { public_token, client_id, client_secret }
233
+ Returns: { data: { access_token, token_type, expires_in } }
610
234
  ```
611
235
 
612
- ## Support
236
+ | Environment | Base URL |
237
+ | ----------- | -------------------------------- |
238
+ | Production | `https://connect-api.kryptos.io` |
613
239
 
614
- - 📧 Email: [support@kryptos.io](mailto:support@kryptos.io)
615
- - 📚 Documentation: [https://docs.kryptos.io](https://docs.kryptos.io)
616
- - 💬 Discord: [Join our community](https://discord.gg/kryptos)
617
- - 🐛 Issues: [GitHub Issues](https://github.com/kryptos/connect-npm-package/issues)
240
+ ---
618
241
 
619
- ## License
242
+ ## Links
620
243
 
621
- MIT © [Kryptos](https://kryptos.io)
244
+ - [Kryptos Developer Portal](https://dashboard.kryptos.io/)
245
+ - [Full docs](https://docs.kryptos.io/)
622
246
 
623
- ---
247
+ ## License
624
248
 
625
- Made with ❤️ by the Kryptos team
249
+ MIT © Kryptos