npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

giwa-react-native-wallet

v0.1.1

Published

GIWA Chain SDK for React Native - Expo and React Native CLI compatible

Downloads

216

Readme

giwa-react-native-wallet

npm version Documentation License: MIT

GIWA Chain SDK for React Native - Expo and React Native CLI compatible

Features

✅ Available Now

| Feature | Hook | Description | |---------|------|-------------| | Wallet Management | useGiwaWallet | Create, recover, import, export wallets | | Balance Query | useBalance | Check ETH and token balances | | Transactions | useTransaction | Send ETH transactions | | Token Operations | useTokens | ERC-20 token transfers and queries | | Flashblocks | useFlashblocks | ~200ms fast preconfirmation | | Dojang (EAS) | useDojang | On-chain attestation service | | Faucet | useFaucet | Testnet ETH faucet | | Network Info | useNetworkInfo | Network status and feature availability | | Biometric Auth | useBiometricAuth | Face ID / Touch ID / Fingerprint | | Secure Storage | - | iOS Keychain / Android Keystore |

🚧 Coming Soon (Contract Deployment Pending)

These features are fully implemented in the SDK, but require smart contract deployment by the GIWA team.

| Feature | Hook | Status | Official Docs | |---------|------|--------|---------------| | L1 Bridge | useBridge | ENS contracts not deployed | GIWA Docs | | GIWA ID | useGiwaId | L1 Bridge contract not deployed | GIWA Docs |

💡 Note: L2 Standard Bridge (l2StandardBridge) is available on OP Stack. Full L1↔L2 bridging requires L1 contract deployment.

For bridge operations, you can use Superbridge in the meantime.

Installation

Expo

# npm
npm install giwa-react-native-wallet expo-secure-store expo-local-authentication react-native-get-random-values

# yarn
yarn add giwa-react-native-wallet expo-secure-store expo-local-authentication react-native-get-random-values

# pnpm
pnpm add giwa-react-native-wallet expo-secure-store expo-local-authentication react-native-get-random-values

Tip: You can also use npx expo install for automatic Expo SDK version compatibility.

React Native CLI

# npm
npm install giwa-react-native-wallet react-native-keychain react-native-get-random-values

# yarn
yarn add giwa-react-native-wallet react-native-keychain react-native-get-random-values

# pnpm
pnpm add giwa-react-native-wallet react-native-keychain react-native-get-random-values
# iOS setup
cd ios && pod install

Quick Start

1. Wrap your app with GiwaProvider

import { GiwaProvider } from "giwa-react-native-wallet";

export default function App() {
  return (
    <GiwaProvider>
      {" "}
      {/* config is optional, defaults to testnet */}
      <YourApp />
    </GiwaProvider>
  );
}

2. Create or recover a wallet

import { useGiwaWallet } from "giwa-react-native-wallet";

function WalletScreen() {
  const { wallet, createWallet, recoverWallet } = useGiwaWallet();

  // createWallet() - no parameters required
  const handleCreate = async () => {
    const { wallet, mnemonic } = await createWallet();
    console.log("Address:", wallet.address);
    // Save mnemonic securely!
  };

  return (
    <View>
      {wallet ? (
        <Text>Address: {wallet.address}</Text>
      ) : (
        <Button title="Create Wallet" onPress={handleCreate} />
      )}
    </View>
  );
}

3. Check balance

import { useBalance } from "giwa-react-native-wallet";

function BalanceScreen() {
  // useBalance() - no parameters required, uses connected wallet
  const { formattedBalance, refetch } = useBalance();

  return (
    <View>
      <Text>Balance: {formattedBalance} ETH</Text>
      <Button title="Refresh" onPress={refetch} />
    </View>
  );
}

4. Send transactions

import { useTransaction } from "giwa-react-native-wallet";

function SendScreen() {
  const { sendTransaction, waitForReceipt, isLoading } = useTransaction();

  const handleSend = async () => {
    const hash = await sendTransaction({
      to: "0x...",
      value: "0.1", // ETH
    });

    const receipt = await waitForReceipt(hash);
    console.log("Confirmed in block:", receipt.blockNumber);
  };

  return (
    <Button title="Send 0.1 ETH" onPress={handleSend} disabled={isLoading} />
  );
}

5. Use Flashblocks for fast confirmations

import { useFlashblocks } from "giwa-react-native-wallet";

function FastTransactionScreen() {
  const { sendTransaction, getAverageLatency } = useFlashblocks();

  const handleSend = async () => {
    const { preconfirmation, result } = await sendTransaction({
      to: "0x...",
      value: BigInt("100000000000000000"), // 0.1 ETH in wei
    });

    console.log("Preconfirmed at:", preconfirmation.preconfirmedAt);

    const receipt = await result.wait();
    console.log("Confirmed at:", receipt.blockNumber);
    console.log("Average latency:", getAverageLatency(), "ms");
  };

  return <Button title="Fast Send" onPress={handleSend} />;
}

6. Resolve GIWA ID

import { useGiwaId } from "giwa-react-native-wallet";

function GiwaIdScreen() {
  const { resolveAddress, resolveName } = useGiwaId();

  const handleResolve = async () => {
    // GIWA ID to address
    const address = await resolveAddress("alice.giwa.id");
    console.log("Address:", address);

    // Address to GIWA ID
    const name = await resolveName("0x...");
    console.log("Name:", name);
  };

  return <Button title="Resolve" onPress={handleResolve} />;
}

API Reference

Hooks

| Hook | Description | Status | | ------------------ | --------------------------------------------------------- | ------ | | useGiwaWallet | Wallet management (create, recover, import, export) | ✅ | | useBalance | ETH balance queries | ✅ | | useTransaction | Send ETH transactions | ✅ | | useTokens | ERC-20 token operations | ✅ | | useBridge | L1↔L2 bridge operations | 🚧 | | useFlashblocks | Fast preconfirmation transactions | ✅ | | useGiwaId | GIWA ID (ENS) resolution | 🚧 | | useDojang | Attestation verification | ✅ | | useFaucet | Testnet faucet | ✅ | | useNetworkInfo | Network status and feature availability | ✅ | | useBiometricAuth | Biometric authentication (Face ID, Touch ID, Fingerprint) | ✅ |

🚧 = Coming soon (contract deployment pending). See GIWA Docs for updates.

Configuration (All Optional)

// Minimal - all defaults
<GiwaProvider>
  <App />
</GiwaProvider>

// With options (all optional)
<GiwaProvider
  network="testnet"           // optional, default: 'testnet'
  initTimeout={10000}         // optional, default: 10000 (ms)
  onError={(e) => console.error(e)}  // optional
>
  <App />
</GiwaProvider>

Custom Endpoints

You can override default network endpoints:

<GiwaProvider
  config={{
    network: 'testnet',
    endpoints: {
      rpcUrl: 'https://my-custom-rpc.example.com',
      flashblocksRpcUrl: 'https://my-flashblocks-rpc.example.com',
      flashblocksWsUrl: 'wss://my-flashblocks-ws.example.com',
      explorerUrl: 'https://my-explorer.example.com',
    },
  }}
>

Access endpoints at runtime:

import { useNetworkInfo } from "giwa-react-native-wallet";

function MyComponent() {
  const { rpcUrl, flashblocksRpcUrl, flashblocksWsUrl, explorerUrl } =
    useNetworkInfo();
  // Use the resolved endpoints
}

Network Selection

Check Network Status and Feature Availability

import { useNetworkInfo } from "giwa-react-native-wallet";

function NetworkStatus() {
  const {
    network,
    isTestnet,
    isReady,
    hasWarnings,
    warnings,
    isFeatureAvailable,
    unavailableFeatures,
  } = useNetworkInfo();

  return (
    <View>
      <Text>Network: {network}</Text>
      <Text>Testnet: {isTestnet ? "Yes" : "No"}</Text>
      <Text>Ready: {isReady ? "Yes" : "No"}</Text>

      {hasWarnings && (
        <View>
          <Text>Warnings:</Text>
          {warnings.map((w, i) => (
            <Text key={i}>- {w}</Text>
          ))}
        </View>
      )}

      {/* Check specific feature availability */}
      {!isFeatureAvailable("giwaId") && (
        <Text>GIWA ID is not available on this network</Text>
      )}
    </View>
  );
}

Network Warnings

When using mainnet with TBD (not yet deployed) contracts, the SDK will log warnings:

[GIWA SDK] Network "mainnet" has 4 warning(s):
  1. [WARNING] Mainnet is not fully ready. 4 feature(s) unavailable.
  2. [WARNING] bridge: L1 Bridge contract is TBD
  3. [WARNING] giwaId: ENS Registry/Resolver contracts are TBD
  4. [WARNING] dojang: EAS/Schema Registry contracts are TBD
[GIWA SDK] Consider using "testnet" for development and testing.

Network Information

Testnet (GIWA Sepolia)

| Property | Value | | --------------------- | ----------------------------------------- | | Chain ID | 91342 | | RPC URL | https://sepolia-rpc.giwa.io | | Flashblocks RPC | https://sepolia-rpc-flashblocks.giwa.io | | Flashblocks WebSocket | wss://sepolia-rpc-flashblocks.giwa.io | | Block Explorer | https://sepolia-explorer.giwa.io | | Currency | ETH |

Mainnet (🚧 Under Development)

⚠️ Mainnet is currently under development. Please use testnet.

| Property | Value | | -------------- | -------------------- | | Chain ID | - | | RPC URL | - | | Block Explorer | - | | Status | 🚧 Under Development |

Security

  • Private keys and mnemonics are stored in iOS Keychain / Android Keystore
  • Biometric authentication support for sensitive operations
  • Secure storage required - SDK will not work without it

Testing

Setup

# Install dev dependencies
npm install --save-dev jest @testing-library/react-native @testing-library/react-hooks

# For TypeScript
npm install --save-dev @types/jest ts-jest

Jest Configuration

// jest.config.js
module.exports = {
  preset: "react-native",
  setupFilesAfterEnv: ["./jest.setup.js"],
  transformIgnorePatterns: [
    "node_modules/(?!(react-native|@react-native|giwa-react-native-wallet)/)",
  ],
  moduleNameMapper: {
    "^giwa-react-native-wallet$":
      "<rootDir>/node_modules/giwa-react-native-wallet/dist/index.js",
  },
};

Mock Setup

// jest.setup.js
jest.mock("expo-secure-store", () => ({
  setItemAsync: jest.fn(),
  getItemAsync: jest.fn(),
  deleteItemAsync: jest.fn(),
  isAvailableAsync: jest.fn(() => Promise.resolve(true)),
  WHEN_UNLOCKED_THIS_DEVICE_ONLY: "WHEN_UNLOCKED_THIS_DEVICE_ONLY",
}));

jest.mock("react-native-keychain", () => ({
  setGenericPassword: jest.fn(() => Promise.resolve(true)),
  getGenericPassword: jest.fn(() => Promise.resolve({ password: "test" })),
  resetGenericPassword: jest.fn(() => Promise.resolve(true)),
  getSupportedBiometryType: jest.fn(() => Promise.resolve("FaceID")),
  ACCESS_CONTROL: { BIOMETRY_CURRENT_SET_OR_DEVICE_PASSCODE: "BIOMETRY" },
  ACCESSIBLE: { WHEN_UNLOCKED_THIS_DEVICE_ONLY: "WHEN_UNLOCKED" },
  BIOMETRY_TYPE: { FACE_ID: "FaceID", TOUCH_ID: "TouchID" },
}));

Unit Test Examples

Testing Wallet Creation

// __tests__/wallet.test.ts
import { renderHook, act } from "@testing-library/react-hooks";
import { useGiwaWallet } from "giwa-react-native-wallet";
import { GiwaProvider } from "giwa-react-native-wallet";

const wrapper = ({ children }) => (
  <GiwaProvider config={{ network: "testnet" }}>{children}</GiwaProvider>
);

describe("useGiwaWallet", () => {
  it("should create a new wallet", async () => {
    const { result } = renderHook(() => useGiwaWallet(), { wrapper });

    await act(async () => {
      const { wallet, mnemonic } = await result.current.createWallet();
      expect(wallet.address).toMatch(/^0x[a-fA-F0-9]{40}$/);
      expect(mnemonic.split(" ")).toHaveLength(12);
    });
  });

  it("should recover wallet from mnemonic", async () => {
    const { result } = renderHook(() => useGiwaWallet(), { wrapper });
    const testMnemonic =
      "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";

    await act(async () => {
      const wallet = await result.current.recoverWallet(testMnemonic);
      expect(wallet.address).toBe("0x9858EfFD232B4033E47d90003D41EC34EcaEda94");
    });
  });

  it("should throw error for invalid mnemonic", async () => {
    const { result } = renderHook(() => useGiwaWallet(), { wrapper });

    await expect(
      result.current.recoverWallet("invalid mnemonic phrase")
    ).rejects.toThrow("Invalid recovery phrase.");
  });
});

Testing Balance Hook

// __tests__/balance.test.ts
import { renderHook, waitFor } from "@testing-library/react-hooks";
import { useBalance } from "giwa-react-native-wallet";

// Mock viem client
jest.mock("viem", () => ({
  ...jest.requireActual("viem"),
  createPublicClient: () => ({
    getBalance: jest.fn(() => Promise.resolve(BigInt("1000000000000000000"))),
  }),
}));

describe("useBalance", () => {
  it("should fetch ETH balance", async () => {
    const { result } = renderHook(() => useBalance("0x1234..."), { wrapper });

    await waitFor(() => {
      expect(result.current.isLoading).toBe(false);
    });

    expect(result.current.formattedBalance).toBe("1.0");
    expect(result.current.balance).toBe(BigInt("1000000000000000000"));
  });
});

Testing Token Transfer

// __tests__/tokens.test.ts
import { renderHook, act } from "@testing-library/react-hooks";
import { useTokens } from "giwa-react-native-wallet";

describe("useTokens", () => {
  it("should transfer tokens", async () => {
    const { result } = renderHook(() => useTokens(), { wrapper });

    await act(async () => {
      const hash = await result.current.transfer(
        "0xTokenAddress...",
        "0xRecipient...",
        "100"
      );
      expect(hash).toMatch(/^0x[a-fA-F0-9]{64}$/);
    });
  });

  it("should get token balance", async () => {
    const { result } = renderHook(() => useTokens(), { wrapper });

    await act(async () => {
      const balance = await result.current.getBalance("0xTokenAddress...");
      expect(balance.token.symbol).toBeDefined();
      expect(balance.formattedBalance).toBeDefined();
    });
  });
});

Testing GIWA ID Resolution

// __tests__/giwaId.test.ts
import { renderHook, act } from "@testing-library/react-hooks";
import { useGiwaId } from "giwa-react-native-wallet";

describe("useGiwaId", () => {
  it("should resolve GIWA ID to address", async () => {
    const { result } = renderHook(() => useGiwaId(), { wrapper });

    await act(async () => {
      const address = await result.current.resolveAddress("alice.giwa.id");
      expect(address).toMatch(/^0x[a-fA-F0-9]{40}$/);
    });
  });

  it("should return null for non-existent GIWA ID", async () => {
    const { result } = renderHook(() => useGiwaId(), { wrapper });

    await act(async () => {
      const address = await result.current.resolveAddress(
        "nonexistent.giwa.id"
      );
      expect(address).toBeNull();
    });
  });
});

Integration Test Example

// __tests__/integration/fullFlow.test.ts
import { renderHook, act } from "@testing-library/react-hooks";
import {
  useGiwaWallet,
  useBalance,
  useTransaction,
} from "giwa-react-native-wallet";

describe("Full Wallet Flow", () => {
  it("should complete full transaction flow", async () => {
    // 1. Create wallet
    const { result: walletResult } = renderHook(() => useGiwaWallet(), {
      wrapper,
    });

    let walletAddress: string;
    await act(async () => {
      const { wallet } = await walletResult.current.createWallet();
      walletAddress = wallet.address;
    });

    // 2. Check balance
    const { result: balanceResult } = renderHook(
      () => useBalance(walletAddress),
      { wrapper }
    );

    await waitFor(() => {
      expect(balanceResult.current.balance).toBeDefined();
    });

    // 3. Send transaction (if balance > 0)
    if (balanceResult.current.balance > 0n) {
      const { result: txResult } = renderHook(() => useTransaction(), {
        wrapper,
      });

      await act(async () => {
        const hash = await txResult.current.sendTransaction({
          to: "0xRecipient...",
          value: "0.001",
        });
        expect(hash).toBeDefined();
      });
    }
  });
});

E2E Test with Detox (Optional)

// e2e/wallet.e2e.ts
describe("Wallet E2E", () => {
  beforeAll(async () => {
    await device.launchApp();
  });

  it("should create wallet and show address", async () => {
    await element(by.id("create-wallet-button")).tap();
    await expect(element(by.id("wallet-address"))).toBeVisible();
  });

  it("should show balance after wallet creation", async () => {
    await expect(element(by.id("balance-display"))).toBeVisible();
  });
});

Running Tests

# Run all tests
npm test

# Run with coverage
npm test -- --coverage

# Run specific test file
npm test -- wallet.test.ts

# Run in watch mode
npm test -- --watch

Requirements

  • React >= 19.0.0
  • React Native >= 0.77.0
  • Expo SDK >= 53 (for Expo projects)
  • expo-secure-store >= 15.0.0 (Expo)
  • expo-local-authentication >= 14.0.0 (Expo, for biometrics)
  • react-native-keychain >= 9.2.0 (React Native CLI)
  • react-native-get-random-values >= 1.11.0

GIWA Official Resources

| Resource | URL | | ------------------------ | --------------------------------------------------------- | | GIWA Documentation | https://docs.giwa.io | | SDK Documentation | https://dev-eyoungmin.github.io/giwa-react-native-wallet/ | | Sample App (GitHub) | https://github.com/dev-eyoungmin/giwa-react-native-samples | | Testnet Faucet | https://faucet.giwa.io | | Block Explorer (Testnet) | https://sepolia-explorer.giwa.io | | Block Explorer (Mainnet) | - | | Bridge (Superbridge) | https://superbridge.app |

License

MIT