npm package: @ramper/native-core
Description: Ramper's React Native SDK helps developers and provide access to the Blockchain through SSO for non-native crypto users.
Author: Ramper
Latest version: 1.0.0

# @ramper/native-core

Ramper's React Native SDK — Blockchain access via SSO for non-crypto-native users. Provides pre-built authentication UI, wallet management, and transaction signing on EVM-compatible chains.

> **Minimum platform requirements:** iOS 14+ · Android API 21+ · React Native 0.70+

---

## Table of Contents

1. [Installation](#installation)
2. [Peer Dependencies](#peer-dependencies)
3. [iOS Setup](#ios-setup)
4. [Android Setup](#android-setup)
5. [Deep Link Configuration](#deep-link-configuration)
6. [Provider Setup](#provider-setup)
7. [Authentication](#authentication)
8. [Wallet UI](#wallet-ui)
9. [Transactions](#transactions)
10. [Supported Chains](#supported-chains)
11. [API Reference](#api-reference)
12. [Build & Publish](#build--publish)

---

## Installation

```sh
npm install @ramper/native-core
# or
yarn add @ramper/native-core
```

---

## Peer Dependencies

All SDK dependencies install automatically. You only need to manually install two **true peer deps** — React Native requires a single shared instance of these across your whole app:

```sh
yarn add react-native-safe-area-context react-native-screens
```

Then run `pod install` on iOS (see [iOS Setup](#ios-setup)).

---

## iOS Setup

### 1. Install CocoaPods

```sh
cd ios && pod install
```

### 2. Enable Swift bridging (if your project is Obj-C)

If your `AppDelegate` is in Objective-C, you must add a Swift bridging header so that native modules like Keychain work correctly.

### 3. AppDelegate — deep link forwarding

**Swift** (`AppDelegate.swift`):

```swift
import React

// Add inside AppDelegate class:
func application(
  _ app: UIApplication,
  open url: URL,
  options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
  return RCTLinkingManager.application(app, open: url, options: options)
}
```

**Objective-C** (`AppDelegate.m`):

```objc
#import <React/RCTLinkingManager.h>

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
            options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}
```

### 4. Reanimated — Babel plugin

Make sure `react-native-reanimated/plugin` is listed in your app's `babel.config.js`:

```js
module.exports = {
  presets: ['module:@react-native/babel-preset'],
  plugins: ['react-native-reanimated/plugin'],
};
```

---

## Android Setup

### 1. Reanimated — Hermes / ProGuard

Follow the official [react-native-reanimated Android setup](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started).

### 2. Permissions

Add to `android/app/src/main/AndroidManifest.xml` inside `<manifest>`:

```xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.VIBRATE" />
```

---

## Deep Link Configuration

The SDK uses deep links to receive authentication and transaction callbacks from the Ramper auth server. You must configure a custom URI scheme matching your **appId**.

> Get an `appId` by registering at the [Ramper Developer Dashboard](https://developer.ramper.xyz).

### iOS — URL Scheme

1. Open your project in Xcode.
2. Select your target → **Info** tab → **URL Types** → **+**.
3. Set **Identifier** to your Bundle ID (e.g. `com.yourcompany.yourapp`).
4. Set **URL Schemes** to `ramper<appId>` — e.g. if your appId is `suyklxmori`, the scheme is `rampersuyklxmori`.

![iOS deep link screenshot 1](https://i.ibb.co/bRPzW40/deep-link-ios-1.jpg)
![iOS deep link screenshot 2](https://i.ibb.co/0Z5tgwr/deep-link-ios-2.jpg)

### Android — Intent Filter

Add inside the `<activity>` tag in `android/app/src/main/AndroidManifest.xml`:

```xml
<intent-filter>
  <!-- Replace <appId> with your actual appId, no angle brackets -->
  <data android:scheme="ramper<appId>" />
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
```

---

## Provider Setup

Wrap your root component with `RamperProvider`. This is the **only** configuration step needed in your app code.

```tsx
import React from 'react';
import { RamperProvider, ChainNameEnum, AUTH_URL_DEFAULT } from '@ramper/native-core';
import App from './App';

export default function Root() {
  return (
    <RamperProvider
      appId="YOUR_APP_ID"           // Required — from developer dashboard
      chain={ChainNameEnum.tomo}    // Default active chain
      locale="en"                   // 'en' | 'kr'
      theme="light"                 // 'light' | 'dark'
      authUrl={AUTH_URL_DEFAULT}    // Ramper auth server URL
      providers={['google', 'apple', 'twitter', 'facebook', 'email', 'telegram']}
      // logo={require('./assets/logo.png')} // Optional custom logo
    >
      <App />
    </RamperProvider>
  );
}
```

### `RamperProvider` props

| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `appId` | `string` | ✅ | — | Your Ramper application ID |
| `chain` | `ChainNameEnum` | — | `tomo` | Default active chain |
| `locale` | `'en' \| 'kr'` | — | `'en'` | UI language |
| `theme` | `'light' \| 'dark'` | — | `'light'` | UI colour theme |
| `authUrl` | `string` | — | Ramper default | Custom auth server URL |
| `providers` | `ProviderType \| ProviderType[]` | — | all | Enabled SSO providers |
| `logo` | `ImageSourcePropType` | — | Ramper logo | Your app logo shown in the login screen |

---

## Authentication

Use the `useRamperService` hook anywhere inside `RamperProvider` to interact with the SDK.

```tsx
import React from 'react';
import { Button, Text, View } from 'react-native';
import { useRamperService } from '@ramper/native-core';

export default function HomeScreen() {
  const { userWallet, onOpenWallet, onLogout } = useRamperService();

  return (
    <View>
      {userWallet.email ? (
        <>
          <Text>Logged in as: {userWallet.email}</Text>
          <Text>Wallet: {userWallet.wallets[0]?.address}</Text>
          <Button title="Open Wallet" onPress={() => onOpenWallet()} />
          <Button title="Logout" onPress={onLogout} />
        </>
      ) : (
        <Button title="Sign In" onPress={() => onOpenWallet()} />
      )}
    </View>
  );
}
```

When `onOpenWallet()` is called for a user who is **not** logged in, the SDK automatically shows the login screen with all configured SSO providers. After a successful login, the same wallet UI screen slides up.

---

## Wallet UI

```tsx
const { onOpenWallet, onCloseWallet } = useRamperService();

// Open the wallet / login bottom sheet
onOpenWallet();

// Open and indicate the user should be returned after action (e.g. post-tx)
onOpenWallet(true);

// Programmatically close
onCloseWallet();
```

---

## Transactions

All transaction methods return Promises and require the user to be authenticated.

### Send Native / ERC-20 Token

```tsx
import { useRamperService } from '@ramper/native-core';

const { sendTransaction } = useRamperService();

const txHash = await sendTransaction({
  contractAddress: '0xTokenContractAddress', // leave empty for native token
  toAddress: '0xRecipientAddress',
  amount: '0.01',                            // human-readable amount
  decimal: 18,                               // token decimals
  tokenSymbol: 'USDT',                       // shown in the confirm UI
});
```

### Approve ERC-20 Allowance

```tsx
const { approve } = useRamperService();

const result = await approve({
  contractAddress: '0xTokenContractAddress',
  spenderAddress: '0xSpenderAddress',
  amount: '1000',
  decimal: 18,
});
```

### Sign a Raw Message

```tsx
const { signMessage } = useRamperService();

const signature = await signMessage('Hello, Ramper!');
```

### Sign Typed Data (EIP-712)

```tsx
const { signTypedData } = useRamperService();

const signature = await signTypedData(
  JSON.stringify(typedDataObject),
  'eth_signTypedData_v4'   // 'eth_signTypedData' | 'eth_signTypedData_v3' | 'eth_signTypedData_v4'
);
```

### Sign a Raw Transaction

```tsx
const { signTransaction } = useRamperService();

const result = await signTransaction(rawTxObject);
```

---

## Supported Chains

| Chain | `ChainNameEnum` value |
|-------|-----------------------|
| Viction (TomoChain) | `ChainNameEnum.tomo` |
| Viction Testnet | `ChainNameEnum.victionTestnet` |
| Ethereum | `ChainNameEnum.ether` |
| BNB Smart Chain | `ChainNameEnum.binanceSmart` |
| Polygon | `ChainNameEnum.matic` |
| zkSync Era | `ChainNameEnum.zkSyncEra` |
| Chiliz | `ChainNameEnum.Chiliz` |
| Sei EVM Mainnet | `ChainNameEnum.seiEvmMainnet` |

---

## API Reference

### `useRamperService()` return values

| Property | Type | Description |
|----------|------|-------------|
| `userWallet` | `UserWallet` | Authenticated user info and wallet addresses |
| `network` | `Chain` | Currently active chain object |
| `networks` | `Chain[]` | All supported chain objects |
| `onOpenWallet` | `(isReturn?: boolean) => void` | Open wallet / login sheet |
| `onCloseWallet` | `() => void` | Close the sheet |
| `onLogout` | `() => void` | Sign out (keeps encrypted key in device) |
| `onClearData` | `() => void` | Sign out and wipe all local data |
| `signMessage` | `(message: string) => Promise<string \| error>` | Sign a plain message |
| `signTypedData` | `(tx: string, type: string) => Promise<string \| error>` | Sign EIP-712 typed data |
| `signTransaction` | `(data: any) => Promise<TTransactionResult>` | Sign a raw transaction |
| `sendTransaction` | `(data: SendTransaction) => Promise<string \| error>` | Send a token transfer |
| `approve` | `(data: ApproveTransaction) => Promise<TTransactionResult>` | Set ERC-20 allowance |
| `convertBalanceToWei` | `(value: string, decimals?) => string` | Convert human amount to wei |

### `UserWallet`

```ts
interface UserWallet {
  email: string;
  provider: 'google' | 'email' | 'facebook' | 'twitter' | 'apple' | 'telegram';
  wallets: { chain: string; address: string }[];
}
```

### `SendTransaction`

```ts
interface SendTransaction {
  contractAddress?: string; // ERC-20 token contract; omit for native token
  toAddress: string;
  amount: string;           // human-readable (e.g. "1.5")
  decimal?: number;         // token decimals, defaults to 18
  tokenSymbol?: string;
}
```

### Available SSO Providers (`ProviderEnum`)

```ts
enum ProviderEnum {
  google      = 'google',
  facebook    = 'facebook',
  twitter     = 'twitter',
  telegram    = 'telegram',
  apple       = 'apple',
  emailDirect = 'emailDirect',
  email       = 'email',
}
```

---

## Build & Publish

### Build

From the repository root (monorepo):

```sh
yarn workspace @ramper/native-core build
```

Or from the `packages/core` directory:

```sh
cd packages/core
yarn build
```

This runs `react-native-builder-bob` and outputs three targets to `lib/`:

| Format | Path | Description |
|--------|------|-------------|
| CommonJS | `lib/commonjs/` | Node / Metro bundler |
| ES Module | `lib/module/` | Tree-shakeable bundler |
| TypeScript | `lib/typescript/` | `.d.ts` declaration files |

### Publish to npm

```sh
# 1. Bump version (semver)
cd packages/core
npm version patch   # or minor / major

# 2. Build
yarn build

# 3. Verify what will be published (dry run)
npm pack --dry-run

# 4. Publish
npm publish --access public
```

> Make sure you are logged in (`npm login`) and the package name `@ramper/native-core` is available under your npm organisation.

### Automated releases (release-it)

A `release-it` configuration is already included. To cut a release with automatic changelog generation:

```sh
cd packages/core
yarn release
```


<b>Note:</b> This SDK is supported on <b>iOS 14</b> and above.

# Installation

### npm

```sh
$ npm install @ramper/react-native-core
```

### yarn

```sh
$ yarn add @ramper/react-native-core
```

## Installing peer dependencies

```sh
$ yarn add query-string react-native-keychain react-native-inappbrowser-reborn @react-native-community/clipboard @react-navigation/bottom-tabs @react-navigation/native @react-navigation/stack accordion-collapse-react-native date-fns react-native-raw-bottom-sheet react-query react-native-gesture-handler react-native-safe-area-context react-native-screens react-native-device-info
```

<b>Note:</b> follow the further installation steps of [react-native-inappbrowser-reborn](https://github.com/proyecto26/react-native-inappbrowser#mostly-automatic-installation) & [react-navigation](https://reactnavigation.org/docs/getting-started/)

## Step 1

```sh
$ cd ios && pod install
```

## Step 2

Secondly, our SDK uses deep links to communicate back with your application. In order to Configure Deep Links, you will need to get an app id by signing up at [deleveroper dashboard](https://developer.ramper.xyz) and apply the following steps:

# iOS

Add the below code in your AppDelegate.m file

```objc
// Add the header at the top of the file:
#import <React/RCTLinkingManager.h>

// Add this above `@end`:
- (BOOL)application:(UIApplication *)application
   openURL:(NSURL *)url
   options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  return [RCTLinkingManager application:application openURL:url options:options];
}
```

Copy your bundle id as shown in the below screenshot:
![Alt text](https://i.ibb.co/bRPzW40/deep-link-ios-1.jpg '5.2')

Paste your bundle id in identifier section and add ramper\<appId\> in the URI Scheme section:
Make sure to not include the brackets <> in the URLScheme
![Alt text](https://i.ibb.co/0Z5tgwr/deep-link-ios-2.jpg '5.3')

# Android

Add the following in your project/adnroid/app/src/main/AndroidManifest.xml file under <b>Activity</b> Tag

```xml
      <intent-filter>
      <!--  Make sure to not include the brackets <> in the scheme -->
        <data android:scheme="ramper<appId>" />
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
      </intent-filter>

      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.VIBRATE" />
```

## Run your app

### iOS

```sh
$ npx react-native run-ios
```

### Android

```sh
$ npx react-native run-android
```

# Usage

In your starting file import Ramper as below

```js
import {RamperProvider} from '@ramper/native-core';
```

call configure passing your <b>appId (required)</b>, <b>locale (default: en)</b>, <b>theme (default: light)</b>, <b>chain (default: tomo)</b>, <b>authUrl (required)</b>

```js
<RamperProvider
  locale="en"
  theme="light"
  appId="suyklxmori"
  chain="tomo"
  authUrl={AUTH_URL_DEFAULT}
>
  {children}
</RamperProvider>;

```

## Authentication

### Show Wallet Screen
We have a pre-built screen that you can use to display all the sign in options for the customer:

```js
import {useRamperService} from '@ramper/native-core';
```

```js
<RamperScreen
  providers={[
    {
      name: 'google' | 'facebook' | 'twitter' | 'apple',
    },
  ]}
  theme="light | dark"
  onSuccess={(user) => {
    //handle user
  }}
  onFailure={(error) => {
    // handle error
  }}
  onClose={() => {}}
  logo={require('mylogo') | { uri: 'mylogourl' }}
  browserProps // optional
/>
```

Check supported browser props for [iOS](https://github.com/proyecto26/react-native-inappbrowser/#ios-options) and [Android](https://github.com/proyecto26/react-native-inappbrowser/#android-options)

### Signing In Directly
If you want to create a custom Sign In page and only allow the user to sign in with a specific provider, you can invoke the signin method directly instead.

```js
import { Auth } from '@ramper/react-native-core';
```

Auth.signin accecpts two parameters <b>Provider (google | facebook | twitter | apple)</b>, <b>browserProps (optional): check supported browser props for [iOS](https://github.com/proyecto26/react-native-inappbrowser/#ios-options) and [Android](https://github.com/proyecto26/react-native-inappbrowser/#android-options)</b>

```js
try {
  let response = await Auth.signin(
    'google' | 'facebook' | 'twitter' | 'apple',
    browserProps //optional,
  );
  // handle response
} catch (error) {
  // handle error
}
```

### Get User
After a user logs in or on app relaunch, you can call the getUser method to get the currently logged-in user's information.

```js
try {
  let user = await Auth.getUser();
  // handle user
} catch (error) {
  // handle error
}
```

## Wallet View
We also provide a Wallet View that allows your user to see their Ethereum wallet balance and conduct common actions.

## Step 1

```sh
$ yarn add @ramper/react-native-evm
```

<b>Note:</b> follow the further installation instruction of [@ramper/react-native-evm](https://www.npmjs.com/package/@ramper/react-native-evm)

## Step 2

```js
import { WalletView } from '@ramper/react-native-core';
import { EthDataProvider } from '@ramper/react-native-evm';
```

## Step 3

### Use the wallet view component like this

```js
<WalletView
  dataProviders={[{ name: 'ethereum', dataProvider: EthDataProvider }]}
  onCLose={() => {}} // will be called when the user clicks on the close button of wallet view
/>
```

<b>Note:</b> before using this component please make sure that the user is logged in by calling getUser method mentioned above.

## Transactions

Please refer to [@ramper/react-native-evm](https://www.npmjs.com/package/@ramper/react-native-evm) for transaction instructions.

## Sign Out

```js
import { Auth } from '@ramper/react-native-core';

try {
  const signout = await Auth.signOut(
    browserProps //optional
  );
  // handle signout
} catch (error) {
  // handle error
}
```