Web SDK

Set up the client-side web SDK for user-controlled wallets in your web application.

The Circle Web SDK enables user-controlled wallets within your web application. Three authentication methods are supported, namely social logins, email, or PIN, which includes security questions for recovery. This allows you to authenticate your users in a seamless way and create user-controlled wallets for them.

By integrating this client-side SDK, your users can securely create wallets and make transactions using social accounts or email. If you choose the PIN authentication method, your users can input sensitive data, like PINs or security answers, in a secure way. Moreover, the SDK encrypts the request body sent by the application, protecting your users' information.

📘

Note:

The Web and Mobile SDKs preserve the user keyshare with the individual, giving them complete control. You must use the SDKs with the user-controlled wallet product. Additionally, the Web and Mobile SDKs support only the user-controlled wallet product.

At Circle, we understand the importance of end-to-end security for your application and the need to create a tailored and seamless user experience for your end-users. Hence, Circle’s SDK also exposes functionality for you to customize the description and layout. See the Web SDK UI Customization API article to customize the SDK.

Install the SDKs

Install using npm:

npm install @circle-fin/w3s-pw-web-sdk

SDK architecture

You must use Web, iOS, or Android SDKs to access the user-controlled Programmable Wallet product. The SDK secures, manages, and communicates with your server to ensure your user’s keyshare, always stays with them and is not exposed to your servers.

To learn more, see SDK Architecture for User-Controlled Wallets.

SDK API references: enums

The Web SDK supports the API reference enums listed in the following sections.

ChallengeType

Enumerates the types of challenges supported.

enum ChallengeType {
  RESTORE_PIN,
  SET_SECURITY_QUESTIONS,
  CREATE_WALLET,
  CREATE_TRANSACTION,
  ACCELERATE_TRANSACTION,
  CANCEL_TRANSACTION,
  CONTRACT_EXECUTION,
  SIGN_MESSAGE,
  SIGN_TYPEDDATA,
  UNKNOWN,
}

ChallengeStatus

Enumerates the possible status for a challenge.

enum ChallengeStatus {
  COMPLETE,
  EXPIRED,
  FAILED,
  IN_PROGRESS,
  PENDING,
}

QuestionType

Enumerates the types of security questions.

enum QuestionType {
  DATE,
  TEXT,
}

ErrorCode

Enumerates the types of error code.

enum ErrorCode {
  unknown = -1,
  success = 0,
  apiParameterMissing = 1,
  apiParameterInvalid = 2,
  forbidden = 3,
  unauthorized = 4,
  retry = 9,
  customerSuspended = 10,
  pending = 11,
  invalidSession = 12,
  invalidPartnerId = 13,
  invalidMessage = 14,
  invalidPhone = 15,
  userAlreadyExisted = 155101,
  userNotFound = 155102,
  userTokenNotFound = 155103,
  userTokenExpired = 155104,
  invalidUserToken = 155105,
  userWasInitialized = 155106,
  userHasSetPin = 155107,
  userHasSetSecurityQuestion = 155108,
  userWasDisabled = 155109,
  userDoesNotSetPinYet = 155110,
  userDoesNotSetSecurityQuestionYet = 155111,
  incorrectUserPin = 155112,
  incorrectDeviceId = 155113,
  incorrectAppId = 155114,
  incorrectSecurityAnswers = 155115,
  invalidChallengeId = 155116,
  invalidApproveContent = 155117,
  invalidEncryptionKey = 155118,
  userPinLocked = 155119,
  securityAnswersLocked = 155120,
  notEnoughFunds = 155201,
  notEnoughBalance = 155202,
  exceedWithdrawLimit = 155203,
  minimumFundsRequired = 155204,
  invalidTransactionFee = 155205,
  rejectedOnAmlScreening = 155206,
  tagRequired = 155207,
  gasLimitTooLow = 155208,
  transactionDataNotEncodedProperly = 155209,
  fullNodeReturnedError = 155210,
  walletSetupRequired = 155211,
  lowerThenMinimumAccountBalance = 155212,
  rejectedByBlockchain = 155213,
  droppedAsPartOfReorg = 155214,
  operationNotSupport = 155215,
  amountBelowMinimum = 155216,
  wrongNftTokenIdNumber = 155217,
  invalidDestinationAddress = 155218,
  tokenWalletChainMismatch = 155219,
  wrongAmountsNumber = 155220,
  walletIsFrozen = 155501,
  maxWalletLimitReached = 155502,
  walletSetIdMutuallyExclusive = 155503,
  metadataUnmatched = 155504,
  userCanceled = 155701,
  launchUiFailed = 155702,
  pinCodeNotMatched = 155703,
  insecurePinCode = 155704,
  hintsMatchAnswers = 155705,
  networkError = 155706,
  biometricsSettingNotEnabled = 155708,
  deviceNotSupportBiometrics = 155709,
  biometricsKeyPermanentlyInvalidated = 155710,
  biometricsUserSkip = 155711,
  biometricsUserDisableForPin = 155712,
  biometricsUserLockout = 155713,
  biometricsUserLockoutPermanent = 155714,
  biometricsUserNotAllowPermission = 155715,
  biometricsInternalError = 155716,
  invalidUserTokenFormat= 155718,
  walletIdNotFound = 156001,
  tokenIdNotFound = 156002,
  transactionIdNotFound = 156003,
  entityCredentialNotFound = 156004,
  walletSetIdNotFound = 156005,
}

SDK API references: interfaces

The Web SDK supports the interfaces listed in the following sections.

Configs

AppSettings

Holds application settings.

  • appId <string> Application ID, retrieved from Circle Web3 Services Console

Authentication

Holds authentication information.

LoginConfigs

Holds login configuration information.

Definitions

  • google: Configuration object for Google login.
    • clientId: The Client ID for Google login.
    • redirectUri: The Redirect URI for Google login.
  • facebook: Configuration object for Facebook login.
    • appId: The App ID for Facebook login.
    • redirectUri: The Redirect URI for Facebook login.
  • apple: Configuration for Apple login, using Firebase.
  • FirebaseOptions: The Firebase configuration object.
  • deviceToken: The token used to identify the device.
  • deviceEncryptionKey: The encryption key used for the device.
  • otpToken: The optional OTP token for verification.

SocialLoginProvider

Challenge

Holds information about a challenge.

ChallengeResult

Holds the result of a challenge.

SignMessageResult

Holds the result of a sign message or sign typed-data challenge.

  • signature <string> Signature result after signing

SignTransactionResult

Holds the result of a sign transaction challenge.

  • signature <string> Signature result after signing
  • txHash <string> Transaction hash
  • signedTransaction <string> Signed transaction

SocialLoginResult

Holds the result of a social login.

EmailLoginResult

Holds the result of an email login.

OauthInfo

Holds the OAuth information.

Error

Holds error information.

SocialLoginCompleteCallback

Callback function for social login completion.

  • error <Error> Presents if error occurs
  • result <SocialLoginResult> | / | undefined > Presents and contains the result of the social login when the login is completed

SecurityQuestion

Holds information about a custom security question.

Localizations

Holds localization settings.

Common

Holds localization settings for common texts.

ConfirmPincode

Holds localization settings for ConfirmInitPincode or ConfirmNewPincode screen.

EnterPincode

Holds localization settings for EnterPincode screen.

NewPincode

Holds localization settings for InitPincode or NewPincode screen.

RecoverPincode

Holds localization settings for RecoverPincode screen.

SecurityConfirm

Holds localization settings for SecurityConfirm screen.

SecurityIntros

Holds localization settings for SecurityIntros screen.

SecurityQuestions

Holds localization settings for SecurityQuestions screen.

SecuritySummary

Holds localization settings for SecuritySummary screen.

SocialEmailConfirmationUI

Holds localization settings for SocialEmailConfirmationUI screen.

TransactionRequest

Holds localization settings for TransactionRequest screen.

ContractInteraction

Holds localization settings for a contract interaction screen.

SignatureRequest

Holds localization settings for a signature request screen.

EmailOtp

Holds localization settings for an email OTP (One-Time Password) screen.

ThemeColor

Holds customization color settings.

Resources

Holds resource urls and properties, such as images or font-family settings. These resource properties should be hosted on a public server. SDK will load these resources from the urls provided.

CustomLinks

Holds custom links.

Class Definition

The Web SDK supports the class definitions listed in the following sections.

W3SSdk

Constructor

Initializes a new instance of W3SSdk.

Methods

execute

Executes a challenge.

setAppSettings

Sets the application settings.

setAuthentication

Sets the authentication information.

updateConfigs

Updates the configurations.

getDeviceId

Gets the device ID.

performLogin

Performs a social login.

  • provider Social login provider
verifyOtp

Verifies the OTP.

execute

Executes a challenge.

setCustomSecurityQuestions

Sets custom security questions.

setLocalizations

Sets custom localizations

setResources

Sets custom resources

setThemeColor

Sets custom theme colors

setCustomLinks

Sets custom links

setOnForgotPin

Sets callback function for ForgotPin button click event

setOnResendOtpEmail

Sets callback function for Resend OTP Email button click event

Sample code

React.js

import React, { useCallback, useEffect, useState } from 'react'
import { ToastContainer, toast } from 'react-toastify'
import TextField from '@mui/material/TextField'
import Button from '@mui/material/Button'
import { W3SSdk } from '@circle-fin/w3s-pw-web-sdk'

let sdk: W3SSdk

function App() {
  useEffect(() => {
    sdk = new W3SSdk({
      configs: {
        appSettings: { appId: 'someAppId' },
        authentication: {
          userToken: 'someUserToken',
          encryptionKey: 'someEncryptionKey'
        },
        socialLoginConfig: {}
      },
      socialLoginCompleteCallback: (error, result) => {
        if (error) {
          toast.error(`Social Login Error: ${error.message ?? 'Error!'}`)
          return
        }
        toast.success(`Social Login Success: ${result?.userToken}`)
      }
    })
  }, [])

  const [appId, setAppId] = useState(localStorage.getItem('appId') || 'someAppId')
  const [userToken, setUserToken] = useState(localStorage.getItem('userToken') || 'someUserToken')
  const [encryptionKey, setEncryptionKey] = useState(localStorage.getItem('encryptionKey') || 'someEncryptionKey')
  const [challengeId, setChallengeId] = useState(localStorage.getItem('challengeId') || 'someChallengeId')

  const onChangeHandler = useCallback(
    (setState, key) => (e) => {
      const value = e.target.value
      setState(value)
      localStorage.setItem(key, value)
    },
    []
  )

  const onSubmit = useCallback(() => {
    sdk.setAppSettings({ appId })
    sdk.setAuthentication({ userToken, encryptionKey })

    sdk.execute(challengeId, (error, result) => {
      if (error) {
        toast.error(`Error: ${error?.message ?? 'Error!'}`)
        return
      }
      toast.success(`Challenge: ${result?.type}, Status: ${result?.status}`)
    })
  }, [appId, userToken, encryptionKey, challengeId])

  return (
    <div className="p-4">
      <TextField
        label="App Id"
        onChange={onChangeHandler(setAppId, 'appId')}
        value={appId}
      />
      <TextField
        label="User Token"
        onChange={onChangeHandler(setUserToken, 'userToken')}
        value={userToken}
      />
      <TextField
        label="Encryption Key"
        onChange={onChangeHandler(setEncryptionKey, 'encryptionKey')}
        value={encryptionKey}
      />
      <TextField
        label="Challenge Id"
        onChange={onChangeHandler(setChallengeId, 'challengeId')}
        value={challengeId}
      />
      <Button variant="contained" color="primary" onClick={onSubmit}>
        Verify Challenge
      </Button>
      <ToastContainer />
    </div>
  )
}

Vanilla JavaScript

// Assume W3SSdk is globally available
let sdk = new W3SSdk({
  configs: {
    appSettings: { appId: 'someAppId' },
    authentication: {
      userToken: 'someUserToken',
      encryptionKey: 'someEncryptionKey'
    },
    socialLoginConfig: {}
  },
  socialLoginCompleteCallback: (error, result) => {
    if (error) {
      console.error(`Social Login Error: ${error.message ?? 'Error!'}`)
      return
    }
    console.log(`Social Login Success: ${result?.userToken}`)
  }
})

// Initialize settings
const initSettings = () => {
  sdk.setAppSettings({
    appId: 'someAppId',
  })
  sdk.setAuthentication({
    userToken: 'someUserToken',
    encryptionKey: 'someEncryptionKey',
  })
}

// Handle form submission
const handleSubmit = () => {
  const challengeId = document.getElementById('challengeId').value

  sdk.execute(challengeId, (error, result) => {
    if (error) {
      console.error(`Error: ${error?.message ?? 'Error!'}`)
      return
    }
    console.log(`Challenge: ${result?.type}, Status: ${result?.status}`)
  })
}

// Initialization
initSettings()

// Listen for button click event
document.getElementById('submitBtn').addEventListener('click', handleSubmit)sdk.execute(challengeId, (error, result) => {
  if (error) {
    toast.error(`Error: ${error?.message ?? 'Error!'}`)
    return
  }
  toast.success(`Challenge: ${result?.type}, Status: ${result?.status}`)
})