
Security News
npm v12 Ships With Install Scripts Off by Default, Begins Deprecating 2FA-Bypass Tokens
npm v12 is generally available, turning install scripts off by default and beginning the deprecation of 2FA-bypass publishing tokens.
@orangecheck/wallet-adapter
Advanced tools
Normalize browser Bitcoin wallets (UniSat, Xverse, Leather, Alby, OKX, Phantom) behind a single sign(message) API. Drop-in React UI: OcWalletPicker (picker only) + OcWalletButton (pick + sign).
@orangecheck/wallet-adapterFull reference: docs.ochk.io/sdk/wallet-adapter — auto-generated from the TypeScript source on every release. Hand-written prose below is the high-level overview; the docs site is the source of truth for every export, type, and signature.
Normalize browser Bitcoin wallets behind a single sign(message) API.
UniSat, Xverse, Leather, Alby — every wallet exposes a different signing API. This package hides that behind one shape:
const sign = getSigner('unisat', { address });
const signature = await sign(message);
Pairs cleanly with <OcChallengeButton sign={sign} /> from @orangecheck/react, or with the lower-level primitives.
yarn add @orangecheck/wallet-adapter
React components are under a subpath to keep the core library zero-dep:
import { detectWallets, getSigner } from '@orangecheck/wallet-adapter';
import { OcWalletButton } from '@orangecheck/wallet-adapter/react';
detectWallets()Return every supported wallet with a detected flag.
import { detectWallets } from '@orangecheck/wallet-adapter';
detectWallets();
// [
// { id: 'unisat', name: 'UniSat', detected: true, installUrl: '...' },
// { id: 'xverse', name: 'Xverse', detected: false, installUrl: '...' },
// { id: 'leather', name: 'Leather', detected: false, installUrl: '...' },
// { id: 'alby', name: 'Alby', detected: true, installUrl: '...' },
// { id: 'manual', name: 'Paste signature (Sparrow / Core / hardware)',
// detected: true, isManual: true }
// ]
Use to render install prompts for missing wallets and "sign with" buttons for installed ones.
getSigner(id, { address })Return a SignFn bound to a particular wallet.
import { getSigner } from '@orangecheck/wallet-adapter';
const sign = getSigner('unisat', { address: userBtcAddress });
const signature = await sign(canonicalMessage);
SignFn is (message: string) => Promise<string>. Throws when the wallet isn't available or the user cancels.
<OcWalletButton /> (React)Pre-built wallet picker that detects installed wallets, lets the user pick one, and calls onSigned with the signature.
import { OcWalletButton } from '@orangecheck/wallet-adapter/react';
<OcWalletButton
address={userBtcAddress}
message={challenge.message}
onSigned={(sig, walletId) => {
console.log(`${walletId} returned`, sig);
postVerify({ signature: sig });
}}
onError={(err) => console.error(err)}
/>;
Props:
| Prop | Type | Notes |
|---|---|---|
address | string | Required by some wallets (Xverse, Leather). |
message | string | Canonical message to sign (e.g. from /api/challenge). |
onSigned | (sig, walletId) => void | Success callback. |
onError | (err, walletId) => void | Failure callback. |
hideUninstalled | boolean | Default false — uninstalled wallets render as install prompts. |
heading | ReactNode | Header text. Default "Sign with your wallet". |
className, style | Pass-through for the root container. |
import { useState } from 'react';
import { OcWalletButton } from '@orangecheck/wallet-adapter/react';
export function SignIn({ address }: { address: string }) {
const [step, setStep] = useState<'idle' | 'ready' | 'done'>('idle');
const [message, setMessage] = useState('');
const [proven, setProven] = useState('');
async function issueChallenge() {
const r = await fetch(`/api/challenge?addr=${address}`);
const { message } = await r.json();
setMessage(message);
setStep('ready');
}
async function handleSigned(signature: string) {
const r = await fetch('/api/challenge', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message, signature }),
});
const body = await r.json();
if (body.ok) {
setProven(body.address);
setStep('done');
}
}
if (step === 'idle') return <button onClick={issueChallenge}>Start sign-in</button>;
if (step === 'ready') {
return <OcWalletButton address={address} message={message} onSigned={handleSigned} />;
}
return <p>Signed in as {proven}</p>;
}
| Wallet | Global | BIP-322 style |
|---|---|---|
| UniSat | window.unisat.signMessage(msg, 'bip322-simple') | Simple |
| Xverse | window.BitcoinProvider.request('signMessage', { address, message, protocol: 'BIP322' }) | Full |
| Leather | window.LeatherProvider.request('signMessage', { message, paymentType: 'p2tr' }) | Full |
| Alby / WebLN | window.webln.signMessage(msg) | Raw message (not BIP-322 on all addresses — works best for 1…) |
| Manual | Browser prompt() | Caller's wallet produces the signature out-of-band |
The shims are duck-typed — we check shape, not just presence of globals, so spoofing wrappers don't produce false positives.
Heads up on Alby:
webln.signMessagesigns raw bytes, not BIP-322. It tends to produce an OrangeCheck-compatible signature on legacy P2PKH addresses (starting with1), but not on segwit (bc1q…) or taproot (bc1p…). For the general case, prefer UniSat / Xverse / Leather, and offer the paste option as a fallback so users on hardware wallets (Sparrow, Bitcoin Core, Ledger) can still sign.
Security note on detection:
XverseProvidersused to pass if it was any truthy value. As of0.1.1we require a callableBitcoinProvider.requestfunction so a bookmarklet or unrelated extension settingwindow.XverseProviders = {}won't register as Xverse.
UniSat fallback: earlier versions silently fell back from
bip322-simpleto the legacy ECDSAsignMessageon any error. That produced signatures segwit/taproot verifiers couldn't accept. As of0.1.1we only sign BIP-322 — if the wallet throws, the error propagates so the caller can suggest switching wallets or using paste mode.
MIT.
FAQs
Normalize browser Bitcoin wallets (UniSat, Xverse, Leather, Alby, OKX, Phantom) behind a single sign(message) API. Drop-in React UI: OcWalletPicker (picker only) + OcWalletButton (pick + sign).
We found that @orangecheck/wallet-adapter demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
npm v12 is generally available, turning install scripts off by default and beginning the deprecation of 2FA-bypass publishing tokens.

Research
/Security News
Socket tracks the activity as Operation “Muck and Load”: a threat actor uses commit-farming workflows, public dead drops, and protected archives to stage Windows RAT and infostealer malware.

Security News
pnpm 11.10 hardens registry auth to block token redirection, tightens pack-app and deploy, and makes the Rust port (v12) installable.