js-gaya-sdk
v1.0.2
Published
Universal pure JavaScript SDK compatible with React Native, Web, and Node.js for wallet/account management, transactions, and Solana swap.
Readme
js-gaya-sdk
Universal pure JavaScript SDK for wallets, transactions, swaps, and PnL across React Native, Web, and Node.js.
- Multi-chain wallet derivation and import (Ethereum/EVM chains + Solana)
- EVM transactions and message signing (ethers v6)
- Solana transactions and Jupiter-based swap helpers
- Lightweight PnL aggregation via Birdeye APIs
- ESM-first: import-friendly in modern bundlers and RN
Installation
npm i js-gaya-sdkReact Native setup (important)
React Native doesn’t ship Node core shims by default. Add a few lightweight polyfills so crypto-safe keys and URL APIs work reliably.
- Install polyfills
npm i react-native-get-random-values react-native-url-polyfill buffer process- Add at the top of your app entry (e.g., index.js or App.js)
import 'react-native-get-random-values';
import 'react-native-url-polyfill/auto';
if (!global.Buffer) global.Buffer = require('buffer').Buffer;
global.process = require('process');- Optional (only if you hit Solana crypto errors on some RN setups)
- react-native-quick-crypto and react-native-securerandom can provide additional WebCrypto/secure RNG support.
Usage
1) Wallets (derive/import)
import {
generateMnemonic,
createWallet,
addAccount,
importWallet,
loadMore,
CHAINS,
CanonicalChainId,
normalizeChainId,
} from 'js-gaya-sdk';
// Generate a mnemonic, then create primary accounts (index 0 across chains)
const mnemonic = generateMnemonic();
const { wallets } = await createWallet(mnemonic);
// Derive next account for a specific chain
const eth1 = await addAccount(CanonicalChainId.ETHEREUM, 1, mnemonic);
// Or derive index N across all chains (returns an array)
const allAt2 = await addAccount(2, mnemonic);
// Load more accounts at an index across all chains
const moreAt3 = await loadMore(3, mnemonic);
// Import by private key/seed
const importedEth = importWallet('evm', '0xYOUR_EVM_PRIVATE_KEY');
const importedSol = importWallet('solana', '<base58_or_hex_32_byte_seed>');
// Normalize chain id/alias (e.g., 'ETH', 'evm', 1 -> 'ethereum')
const canonical = normalizeChainId('evm'); // 'ethereum'- Supported chains via CHAINS and CanonicalChainId: ethereum, bsc, arbitrum, avalanche, base, solana.
- EVM derivation path: m/44'/60'/0'/0/index; Solana derivation path: m/44'/501'/index'/0'.
### 2) EVM transactions and signing
```js
import { sendEvmTransaction, estimateEvmGas, signEvmMessage } from 'js-gaya-sdk';
// Estimate gas
const gas = await estimateEvmGas({
rpcUrl: 'https://mainnet.infura.io/v3/<key>',
from: '0xYourAddress',
to: '0xRecipient',
valueWei: '1000000000000000', // 0.001 ETH
});
// Send transaction
const res = await sendEvmTransaction({
rpcUrl: 'https://mainnet.infura.io/v3/<key>',
privateKey: '0xYOUR_EVM_PRIVATE_KEY',
to: '0xRecipient',
valueWei: '1000000000000000',
});
// res: { hash, status }
// Sign a message
const sig = await signEvmMessage({ privateKey: '0xYOUR_EVM_PRIVATE_KEY', message: 'hello' });3) Solana transactions
import { Connection, SystemProgram, PublicKey, Keypair, TransactionInstruction } from '@solana/web3.js';
import { sendSolanaTransaction, confirmSolanaTransaction } from 'js-gaya-sdk';
import bs58 from 'bs58';
const connection = new Connection('https://api.mainnet-beta.solana.com');
// Example: simple transfer instruction (lamports)
const fromSecretBase58 = '<BASE58_SECRET_KEY>'; // keep safe!
const payer = Keypair.fromSecretKey(bs58.decode(fromSecretBase58));
const toPubkey = new PublicKey('<RECIPIENT_PUBKEY>');
const ix = SystemProgram.transfer({ fromPubkey: payer.publicKey, toPubkey, lamports: 1000 });
const signature = await sendSolanaTransaction({
connection,
instructions: [ix],
payerSecretKeyBase58: fromSecretBase58,
});
const status = await confirmSolanaTransaction({ connection, signature });4) Solana swaps (Jupiter)
import { Connection } from '@solana/web3.js';
import { getSolanaUrls, submitSolanaSwapQuote, confirmSolanaSwap } from 'js-gaya-sdk';
const { rpcUrl } = getSolanaUrls();
const connection = new Connection(rpcUrl);
const submit = await submitSolanaSwapQuote({
inputToken: 'So11111111111111111111111111111111111111112', // WSOL
outputToken: '<MINT_ADDRESS>',
amount: 1000000, // in smallest units (e.g., lamports for WSOL)
slippage: 50, // basis points (0.50%)
walletAddress: '<YOUR_PUBKEY>',
secretKey: '<BASE58_SECRET_KEY>',
}, connection);
const result = await confirmSolanaSwap({ signature: submit.signature }, connection);5) PnL
The default getPnL exported here is the addresses-based variant (multi-chain). For the tokens-based version use getPnLLegacy.
import { getPnL, getPnLLegacy } from 'js-gaya-sdk';
// Addresses-based (recommended):
const pnl = await getPnL({
ethAddress: '0x...',
bscAddress: '0x...',
solAddress: '...',
refresh: true,
});
// Tokens-based (legacy):
const legacy = await getPnLLegacy({
tokens: [
{ contractAddress: '0x6b175474e89094c44da98b954eedeac495271d0f', symbol: 'DAI', balance: '1000000000000000000', network: 'eth-mainnet', wallet: '0x...' },
],
chain: 'eth',
});6) Utilities: storage + AES helpers
import { createStorageAdapter, encryptAES, decryptAES } from 'js-gaya-sdk';
// Environment-aware storage: RN -> AsyncStorage (if installed), Web -> localStorage, Node -> in-memory
const storage = createStorageAdapter();
// Store an encrypted secret
await storage.setItem('secret', encryptAES('0xYOUR_EVM_PRIVATE_KEY', 'passphrase'));
// Retrieve and decrypt
const enc = await storage.getItem('secret');
const decrypted = decryptAES(enc, 'passphrase'); // '0xYOUR_EVM_PRIVATE_KEY'Notes:
- In React Native, install @react-native-async-storage/async-storage for persistent storage.
- If AsyncStorage is not available, a temporary in-memory store is used (app restarts will clear it).
API exports overview
This package exposes the following functions and constants for React Native, Web, and Node usage:
- Wallets: createWallet(mnemonic), importWallet(chainId, privateKey), addAccount(chainId, index, mnemonic) or addAccount(index, mnemonic), loadMore(index, mnemonic), CHAINS, CanonicalChainId, normalizeChainId(input), generateMnemonic()
- EVM: sendEvmTransaction({ rpcUrl, privateKey, to, valueWei, data }), estimateEvmGas({ rpcUrl, from, to, data, valueWei }), signEvmMessage({ privateKey, message })
- Solana TX: sendSolanaTransaction({ connection, instructions, payerSecretKeyBase58 }), confirmSolanaTransaction({ connection, signature, maxRetries?, retryDelayMs? })
- Solana Swap (Jupiter): getSolanaUrls({ rpcUrl?, wsUrl? }), submitSolanaSwapQuote(params, connection), confirmSolanaSwap({ signature }, connection), instructionDataToTransactionInstruction(ix)
- Aliases: submitQuote(params, connection) and confirmTransaction(params, connection) mirror the swap helpers
- Utilities: createStorageAdapter(), encryptAES(plaintext, passphrase), decryptAES(ciphertext, passphrase)
Tips:
- For EVM values, pass valueWei as a string that fits in BigInt (e.g., '1000000000000000').
- In Node environments without global fetch, provide one (e.g., undici) before calling PnL or swap helpers.
React Native Integration Guide (Comprehensive)
This section consolidates everything you need to integrate js-gaya-sdk into a React Native app from scratch, including setup, example flows, and troubleshooting.
Prerequisites
- React Native 0.70+ recommended (Hermes enabled by default)
- Node 16+ recommended
- iOS: Xcode + CocoaPods; Android: recent Android SDK/NDK via Android Studio
Platform setup
- iOS: after installing packages, run
cd ios && pod install && cd .. - Android: no extra steps typically required beyond a normal RN project setup
Minimal usage checklist
- Add polyfills at the very top of your entry file before importing this SDK
- Keep mnemonics/private keys outside Redux/plain AsyncStorage; use secure storage
- Verify network permissions in AndroidManifest/iOS target
Troubleshooting
- Error: "Can't find variable: Buffer" → Ensure Buffer polyfill is set before any SDK import
- Error: getRandomValues not available → Ensure
react-native-get-random-valuesimport is at the top of your entry file - Error: "process is not defined" → Ensure
global.process = require('process')is set early - EVM BigInt/math issues → Use a modern RN/Hermes version and avoid transpiling away BigInt
- Network request failures → Check device/emulator network permissions and RPC/API URLs
- iOS build fails after adding packages → Run
pod installinside the ios directory
Organizing keys securely
- Never commit mnemonics or private keys
- Prefer secure storage (Keychain/Keystore) via a library and inject keys at runtime when needed
- Consider using an embedded lightweight wallet flow or integrating with a connector (e.g., WalletConnect for EVM) if you don’t want to handle private keys directly
Networking & environment
- The SDK fetches public APIs (e.g., Jupiter for swaps, Birdeye for PnL)
- Ensure network permissions are enabled in AndroidManifest and iOS Info.plist
- Keep RPC/API keys secure (do not hardcode in source); provide via build-time config
- In Node, provide a global fetch (e.g., undici) before calling PnL or swap helpers
TypeScript usage
- The SDK is authored in JavaScript; you can add local ambient typings or rely on JSDoc
- Keep function inputs as plain objects as shown in examples to retain clear call sites
Production checklist
- Use HTTPS RPC endpoints and rotate API keys
- Add runtime guards for chain IDs, addresses, amounts, and slippage
- Prompt users to confirm actions and show fee/price impact
- Handle and surface errors clearly; add retry/backoff where appropriate
- Encrypt sensitive values at rest using
encryptAESand store viacreateStorageAdapter
That’s it—you’re ready to use js-gaya-sdk in your React Native app. If anything is unclear, share your app setup (RN version, platform, error logs) and I can tailor the guidance further.
