@chipi-stack/chipi-react
v14.12.1
Published
React hooks and components for Chipi SDK
Downloads
1,045
Readme
@chipi-stack/chipi-react
React hooks for Chipi Pay. Provides wallet creation, transfers, SKU purchases, and session management.
Install
npm install @chipi-stack/chipi-react @chipi-stack/backend @chipi-stack/typesQuick Start
import { ChipiProvider, useChipiWallet, useTransfer } from "@chipi-stack/chipi-react";
import type { ChainToken } from "@chipi-stack/types";
function App() {
return (
<ChipiProvider config={{ apiPublicKey: "your-key" }}>
<Wallet />
</ChipiProvider>
);
}
function Wallet() {
const { wallet } = useChipiWallet({
externalUserId: "user-123",
getBearerToken: async () => "your-bearer-token",
});
const { transfer, isLoading } = useTransfer();
if (!wallet) return <p>Loading wallet...</p>;
return (
<button
onClick={() =>
transfer({
params: {
wallet,
token: "USDC" as ChainToken,
recipient: "0x...",
amount: 10,
encryptKey: "user-pin",
},
bearerToken: "your-bearer-token",
})
}
>
{isLoading ? "Sending..." : "Send 10 USDC"}
</button>
);
}Scoping the passkey prompt
useCallAnyContract, useApprove and useTransfer accept an optional
credentialId alongside externalUserId. It scopes the WebAuthn prompt to one
credential instead of letting the authenticator choose:
await callAnyContractAsync({
params: {
usePasskey: true,
externalUserId,
credentialId, // scopes the biometric prompt
wallet,
contractAddress,
calls,
},
bearerToken,
});Reach for it when a user holds more than one Chipi credential on the same device, for example a wallet that was reset or a per-entity wallet, where the unscoped prompt can resolve to the wrong credential and derive a key for the wrong wallet.
Omitting it produces exactly the prompt you get today. credentialId is a
client-side concern and never reaches the API.
What you can ship
- Crypto checkout components — drop-in payment UIs for e-commerce and SaaS
- In-app token transfer UIs — send and receive USDC with a few lines of React
- Connect-with-passkey flows — biometric wallet login without seed phrases
- DeFi dashboards and loyalty/rewards redemption interfaces — display balances, history, and reward claims
- Multisig treasury governance — propose/approve/execute any contract action with N-of-M approvals (see
/multisigbelow)
Have an idea? Tell us what you want to build
Multisig governance (@chipi-stack/chipi-react/multisig)
Tree-shakeable subpath for SHHH multisig: propose any contract action (or a vote), collect N-of-M approvals, execute. Experimental — the API may change.
Describe your actions once as typed templates, then drive them with hooks. The hooks are auth- and chain-agnostic: you pass a MultisigTransport (your coordination backend) and a MultisigSigner (per-owner OE signer), and own the UI.
import {
defineActions, voteTemplate, u256, toFelt,
useProposeAction, useTreasuryProposals,
type MultisigTransport, type MultisigSigner,
} from "@chipi-stack/chipi-react/multisig";
// 1. Register your action templates (vote ships built-in).
const ACTIONS = defineActions([
voteTemplate({ governanceContract: "0x…" }),
{
key: "stake",
label: "Stake",
fields: [{ name: "amount", label: "Amount", type: "amount", decimals: 18 }],
toCalls: (v) => [{ to: "0x…", entrypoint: "stake", calldata: u256(v.amount) }],
title: (v) => `Stake ${v.amount}`,
},
]);
// 2. Propose → approve → execute (you supply transport + signer).
function Governance({ walletAddress, transport, signer }: {
walletAddress: string; transport: MultisigTransport; signer: MultisigSigner;
}) {
const propose = useProposeAction({
walletAddress, transport, signer,
getRequiredApprovals: async () => 2, // read your wallet's threshold
});
const { proposals, approve, execute } = useTreasuryProposals({ walletAddress, transport, signer });
// render your own UI on top of these
}The pure pieces — defineActions, voteTemplate, the toFelt/u256/amountToBase encoders, and the OE core (buildActionProposal/signActionApproval/assembleActionExecuteCalldata) — have no React or network dependency, so templates and calldata are unit-testable in isolation.
Documentation
Full docs at docs.chipipay.com
License
MIT
Private balances (useShield / useUnshield / usePrivateBalance)
import { useShield, usePrivateBalance, derivePrivacyAccount } from "@chipi-stack/chipi-react";
const keys = await derivePrivacyAccount({
anchorSecret,
seedDomainTag: wallet.address,
classHash: COMPANION_CLASS_HASH,
});
const { shieldAsync } = useShield();
await shieldAsync({
config: {
apiPublicKey,
getBearerToken: () => getToken(),
gatewaySubmitUrl: "/api/starknet-gateway", // browsers need this CORS proxy
},
keys,
token: USDC_ADDRESS,
amount: 1_000_000n,
fundDeposit: (companion, amount) => transferGasless(companion, amount),
onStep: setPhase, // prepare | fund | deposit | prove | finish
});
const { byToken } = usePrivateBalance({ mode: "ledger", events: recordedEvents });Client-derived keys (cache the address, never the keys; the DELEGATED PROVER sees the pool key per op — privacy holds vs the public, not the proving operator: see the docs' trust-model section), gasless for the end user (Chipi fronts the STRK per allowlisted API key). Capture the StarkWare pool ToS at the first shield. Full guide in the docs.
