For your customers using Paper Wallets, we provide an easy way to authenticate their identity so that you can focus on delivering the benefits and utility. <VerifyOwnershipWithPaper>
provides a button which opens a pop-up for user's to sign into their Paper Wallets. The implementation follows the OAuth2 specification.
Note: This flow will allow users to sign-up as well and will automatically create a Paper Wallet behind the scenes for the user. To specifically create a Paper Wallet without having users login.


VerifyOwnershipWithPaper
button


Getting Stared
- Head to the Developer Dashboard.
- Click on the "developers" tab.
- Create a new OAuth Client.


- The newly created client will produce a Client ID. Pass this ID into the
<PaperSDKProvider>
. You can now use the<VerifyOwnershipWithPaper>
component to add to your login page.
The main prop for <VerifyOwnershipWithPaper>
is the onSuccess prop. This is a function which will be passed with a code which your backend will use to exchange with a permanent user token (as long as the user doesn't revoke access). See the code sample for more details.
Code Snippet
export function VerifyComponent() {
const onSuccessLogin = async (code: string) => {
// code is the temporary access code that you can swap for a permenant user access token
const resp = await fetch("/api/get-user-token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
code,
}),
});
if (resp.status !== 200) {
console.log("resp", resp);
throw new Error("Failed to get user token");
}
const { userToken } = await resp.json();
};
// Ensure that you have a PaperSDKProvider set-up with the proper chain name and client Id.
return (
<PaperSDKProvider clientId="Your_client_id_here">
<VerifyOwnershipWithPaper onSuccess={onSuccessLogin} />
</PaperSDKProvider>
);
}
import { NextApiRequest, NextApiResponse } from "next";
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== "POST") {
return res.status(404).json({ error: "Method not allowed" });
}
const body: { code: string } = req.body;
const code = body.code;
const resp = await fetch("https://paper.xyz/api/v1/oauth/token", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer <YOUR-API-SECRET-KEY>",
},
body: JSON.stringify({
code,
clientId: "<YOUR-CLIENT-ID>",
}),
});
if (resp.status !== 200) {
return res.status(500).json({ error: "Error getting user token" });
}
const { userToken } = await resp.json();
return res.status(200).json({ userToken });
}
Customization
In order to customize the button to your liking, we provide three ways of using the <VerifyOwnershipWithPaper>
component:
Provided Button:


VerifyOwnershipWithPaper
button
<VerifyOwnershipWithPaper className='verify-ownership-with-paper-btn' onSuccess={onSuccessLogin} />
Wrapping your own login Button with the <VerifyOwnershipWithPaper>
component:
<VerifyOwnershipWithPaper onSuccess={onSuccessLogin}>
<YourComponentHere />
</VerifyOwnershipWithPaper>
Control everything yourself:
<VerifyOwnershipWithPaper onSuccess={onSuccessLogin}>
{({ onClick } : { onClick : () => void}) => {
return <YourButtonHere onClick={onClick} />
}}
</VerifyOwnershipWithPaper>
Props
These props can be used as arguments within the <VerifyOwnershipWithPaper>
component. See the name, type, and description for each prop in the table below.
Prop | Type | Description |
---|---|---|
className | string | Optional |
Callback Functions
The following callback function can be passed on as arguments within the <VerifyOwnershipWithPaper>
component. See the name, type, and description for each prop in the table below.
Callback Function | Description |
---|---|
onSuccess: (code: string) => void | Optional |
onError: (error: PaperSDKError) => void | Optional |
onClose: () => void | Optional |