The @abstraxn/signer-react and @abstraxn/signer-core packages help you add embedded and external wallet onboarding to your dApp.
1. Installation
Install both SDK packages using your preferred package manager:
npm i @abstraxn/signer-react @abstraxn/signer-core
2. Get Your API Key
- Visit https://dashboard.abstraxn.com/
- Log in or sign up
- Go to Apps and click Create New App
- Navigate to Wallets and click Add Wallet Service
- Click View Details and copy your API key
Keep your API key in environment variables. Do not hardcode it in client code.
3. Setup Provider
Wrap your app with AbstraxnProvider:
import { AbstraxnProvider } from "@abstraxn/signer-react";
export function AppProviders({ children }: { children: React.ReactNode }) {
return (
<AbstraxnProvider
config={{
apiKey: process.env.NEXT_PUBLIC_ABSTRAXN_API_KEY || "YOUR_API_KEY",
}}
>
{children}
</AbstraxnProvider>
);
}
3b. Enable Solana Gasless Transactions (Optional)
If your app supports Solana, you can enable gasless transactions by adding the solanaGasless option to your provider config. This uses the same gas sponsorship model as the Solana Relayer — fees are paid from your paymaster gas pool.
import { AbstraxnProvider } from "@abstraxn/signer-react";
export function AppProviders({ children }: { children: React.ReactNode }) {
return (
<AbstraxnProvider
config={{
apiKey: process.env.NEXT_PUBLIC_ABSTRAXN_API_KEY || "YOUR_API_KEY",
solanaGasless: {
enabled: true,
relayerUrl: process.env.NEXT_PUBLIC_SOLANA_RELAYER_URL!,
// e.g. "https://solana-paymaster.abstraxn.com/api/v1/103/?apikey=your_api_key"
},
}}
>
{children}
</AbstraxnProvider>
);
}
To get your Solana relayer URL, go to your Abstraxn Dashboard → Paymaster — if your app has Solana selected, you will see the Solana paymaster link.
4. Connect Wallet
Use the built-in connect UI:
import { ConnectButton } from "@abstraxn/signer-react";
export function WalletButton() {
return <ConnectButton connectText="Connect Wallet" />;
}
5. Send a Transaction (Current Flow)
Use usePrepareRawTxn -> useSignAndSendTxn -> useWaitForTxnReceipt.
import { useState } from "react";
import {
useAddress,
useIsConnected,
usePublicClient,
usePrepareRawTxn,
useSignAndSendTxn,
useWaitForTxnReceipt,
useEstimateGas,
useGetGasPrice,
} from "@abstraxn/signer-react";
import { polygonAmoy } from "viem/chains";
import { parseEther } from "viem";
export function SendTransaction() {
const address = useAddress();
const isConnected = useIsConnected();
const [sending, setSending] = useState(false);
const [hash, setHash] = useState<`0x${string}` | null>(null);
const { publicClient } = usePublicClient(
polygonAmoy,
"https://rpc-amoy.polygon.technology"
);
const { prepareRawTxn } = usePrepareRawTxn(publicClient);
const { signAndSendTxn } = useSignAndSendTxn(publicClient);
const { waitForTxnReceipt } = useWaitForTxnReceipt(publicClient);
const { estimateGas } = useEstimateGas(publicClient);
const { getGasPrice } = useGetGasPrice(publicClient);
const handleSend = async () => {
if (!isConnected || !address) return;
setSending(true);
try {
const rawTx = await prepareRawTxn({
from: address as `0x${string}`,
to: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
value: parseEther("0.001"),
});
const { gasLimit } = await estimateGas({
account: address as `0x${string}`,
to: rawTx.to,
data: rawTx.data,
value: rawTx.value,
});
const fees = await getGasPrice();
const result = await signAndSendTxn({
from: address as `0x${string}`,
...rawTx,
gas: {
gasLimit,
maxFeePerGas: fees.maxFeePerGas,
maxPriorityFeePerGas: fees.maxPriorityFeePerGas,
gasPrice: fees.gasPrice,
},
});
setHash(result.hash as `0x${string}`);
await waitForTxnReceipt({ hash: result.hash as `0x${string}`, confirmations: 1 });
} finally {
setSending(false);
}
};
return (
<button onClick={handleSend} disabled={!isConnected || sending}>
{sending ? "Sending..." : "Send 0.001 MATIC"}
</button>
);
}
Useful Links