@sprinkles-web3/callback
TypeScript icon, indicating that this package has built-in type declarations

1.3.0 • Public • Published

Sprinkles Web3 Callback for JS

Utility to parse the callback request containing the result of the user's action as a response to your app's inquiry.

Example: To sign a user into your app, you create a Sprinkles /auth URL and open it in a new window/popup. If the user decides to authenticate, the user (via Sprinkles web app) will make a request to your callback endpoint containing the user's address with their signature.

To create a Sprinkles URL, use @sprinkles-web3/client NPM package.

Get started

npm install @sprinkles-web3/callback

Setting up callback endpoint

You will need 1 callback endpoint for each Sprinkles callback request.

This instruction assumes that you already have a running JS web server. If you need to create a server, we recommend create-next-app.

  1. Identify a path that can be used as a callback endpoint, e.g. /api/sprinkles-auth-callback for sign up/in use case.

  2. The callback endpoint will receive a POST request directly from the user's device with origin: https://auth.sprinkles.app. Hence, you will need to enable cors for that domain. See the section below on how to set up.

Setting up cors for callback endpoint

This instruction assumes that we will be using a cors middleware on a Next.js web server.

  1. Install cors.
npm install cors
  1. On your callback endpoint, e.g. /api/sprinkles-auth-callback.ts, wire-in the middleware.
import Cors from 'cors';

const corsForSprinkles = Cors({
  methods: ['POST'],
  origin: 'https://auth.sprinkles.app',
});

const runCorsMiddleware = (req: NextApiRequest, res: NextApiResponse<Data>) => {
  return new Promise((resolve, reject) => {
    corsForSprinkles(req, res, (result) => {
      if (result instanceof Error) {
        return reject(result);
      }
      return resolve(result);
    });
  });
};

const handler = async (req: NextApiRequest, res: NextApiResponse<Data>) => {
  if (req.method !== 'POST') {
    // If it's not a POST request, ignore the request.
    res.status(500).end();
    return;
  }

  await runCorsMiddleware(req, res);

  // The rest of your callback endpoint code goes here.
  ...
  ...
}

Sign up/in with Sprinkles

This utility will parse the callback request containing the result of the user's action on Sprinkles /auth window/popup. The request will have a globally unique sid (previously generated by your app) and the standard signing attributes (i.e. address, rp signature, timestamp), signed by the user.

  1. Set up a callback endpoint on your web server for this use case, e.g. /api/sprinkles-auth-callback. See the section above on how to set up.

  2. Upon a successful verification, you will receive the user's wallet address. Store the mapping between sid and the user's wallet address in your database. Any subsequent request bearing the sid can be associated with the wallet address, i.e. logged in.

The code for your callback endpoint, e.g. /api/sprinkles-auth-callback.ts, should look like this:

import {
  SprinklesHttpError,
  validateAuthCallback,
} from '@sprinkles-web3/callback';

// For security purpose, only allow signed message directed by and for your web URL, e.g. https://example.com.
const AllowedRelyingParty = ...

const handler = async (req: NextApiRequest, res: NextApiResponse<Data>) => {
  if (req.method !== 'POST') {
    // If it's not a POST request, ignore the request.
    res.status(500).end();
    return;
  }

  // This is the cors middleware.
  await runCorsMiddleware(req, res);

  try {
    // This throws an error if the Auth callback is malformed, expired, forged, or fraudulent.
    const { address, sid } = validateAuthCallback(req.body, {
      allowedRp: AllowedRelyingParty,
    });

    // Subsequent request presenting the sid should be considered authenticated using the address.
    // To do so, store the sid -> wallet address in your database, e.g.
    await myDatabase.put(sid, address);

    // Don't forget to return HTTP 200 OK.
    res.status(200).end();
    return;

  } catch (e) {
    if (e instanceof SprinklesHttpError) {
      // Error caught by Sprinkles.
      // This is most likely caused by the user, not by Sprinkles.
      res.status(e.httpStatus).write(e.responseBody());
      return;
    }

    // Else, handle error when storing sid -> address in your database.
    // If it's an issue on your server, return HTTP 500.

    // Unknown error.
    res.status(500).end();
    return;
  }
}

Requesting user's information

App developers are able to request user's information via Sprinkles. The user can select which information they are consent to provide to the app developers.

To do so, provide the userItems parameter to authUrl() function in @sprinkles-web3/client.

...
...

const userItems: UserItemsRequest =  {
  verifiedEmailAddress: { required: true },
  verifiedPhoneNumber: { required: false },
};

const sprinklesAuthUrl = authUrl(
  sid,
  callbackUrl,
  userItems    // This is the user information being requested.
);

...
...

If the user consents, the information will be delivered along with their signature to your Sprinkles callback function.

const {
  address,
  rp,
  sid,
  signature,
  timestamp,
  data, // This is where the user information will be stored.
} = validateAuthCallback(requestBodyStr, {
  allowedRp: AllowedRelyingParty,
});

The data field will look as such:

{
  userItems: {
    verifiedEmailAddress: 'test@example.com',
    verifiedPhoneNumber: '+15551112222'
  }
}

Sending a transaction with Sprinkles

This utility will parse the callback request containing the result of the user's action on Sprinkles /send-tx window/popup. The request will have a globally unique sid (previously generated by your app), standard signing attributes (i.e. address, rp signature, timestamp), and the transaction response inside data.createEvmTx.

  1. This functionality uses the same callback endpoint that you may have already set up. See the section above on how to set up.

  2. Upon a successful transaction submission, you will receive the transaction hash, i.e. data.createEvmTx.txHash. Store the mapping between the sid and the txHash in your transaction database. Your app can now query your database to find the transaction response using their sid.

The following illustrates the specific fields related to the transaction.

const {
  address,
  rp,
  sid,
  signature,
  timestamp,
  data, // This is where the transaction hash will be returned.
} = validateAuthCallback(requestBodyStr, {
  allowedRp: AllowedRelyingParty,
});

The data field will look as such:

{
  createEvmTx: {
    chainId: 1,
    txHash: '0x12345...'
  }
}

The overall code for your callback endpoint, e.g. /api/sprinkles-auth-callback.ts, may look like this:

import {
  SprinklesHttpError,
  validateAuthCallback,
} from '@sprinkles-web3/callback';

// For security purpose, only allow signed message directed by and for your web URL, e.g. https://example.com.
const AllowedRelyingParty = ...

const handler = async (req: NextApiRequest, res: NextApiResponse<Data>) => {
  if (req.method !== 'POST') {
    // If it's not a POST request, ignore the request.
    res.status(500).end();
    return;
  }

  // This is the cors middleware.
  await runCorsMiddleware(req, res);

  try {
    // This throws an error if the Auth callback is malformed, expired, forged, or fraudulent.
    const { sid, data } = validateAuthCallback(req.body, {
      allowedRp: AllowedRelyingParty,
    });

    if (!!data?.createEvmTx?.txHash) {
      // Upon returning to your app, you can use the sid to retrieve the user's transaction status.
      // To do so, store the sid -> txHash in your database, e.g.
      await myTxDatabase.put(sid, data.createEvmTx.txHash);
    }

    // Don't forget to return HTTP 200 OK.
    res.status(200).end();
    return;

  } catch (e) {
    if (e instanceof SprinklesHttpError) {
      // Error caught by Sprinkles.
      // This is most likely caused by the user, not by Sprinkles.
      res.status(e.httpStatus).write(e.responseBody());
      return;
    }

    // Else, handle error when storing sid -> address in your database.
    // If it's an issue on your server, return HTTP 500.

    // Unknown error.
    res.status(500).end();
    return;
  }
}

Contact

Discord

Email: team@sprinkles.app

Package Sidebar

Install

npm i @sprinkles-web3/callback

Weekly Downloads

4

Version

1.3.0

License

ISC

Unpacked Size

49.2 kB

Total Files

19

Last publish

Collaborators

  • jmargatan