If you want to test in the iOS or Android environment, you can check our Github repo for iOS sample app and Android sample app. React Native sample app is coming soon.
Learn how to initialize and create a user-controlled wallet using the social logins. To create a wallet with email authentication, see Create Your First Wallet with Email.
This quickstart utilizes Circle's sample application in combination with API requests that can be sent using cURL requests or Circle's API references. cURL requests are provided inline while API references call the API endpoints. For more information on how to use API references to make calls, see Testing API References.
You can create both Smart Contract Accounts (SCA) and Externally Owned Accounts (EOA) wallets. To learn more, see the Account Type guide.
Before you begin:
This guide walks you through steps on how to create a wallet and perform transactions or signatures, and provides sample code. You can use Circle's sample app on web or set it up locally.
If you want to test in the iOS or Android environment, you can check our Github repo for iOS sample app and Android sample app. React Native sample app is coming soon.
GET
request to the /config/entity
endpoint and copy the appId
from the response body.The sample app generates and pre-populates the device ID for you. During actual implementation, you must retrieve it by calling the Client-side SDK method getDeviceId
.
You should not call the getDeviceId
method while the authentication process is
still running because the method will open an invisible modal to retrieve the
device ID, which will replace the one being used for authentication and
interrupt the ongoing authentication process. Call getDeviceId
before calling
performLogin
in step 4.
Only Google and Facebook login options are available for testing in the sample app. Apple login is not available due to a restriction on URL redirection for OAuth integration with Apple login through Firebase.
Obtain IDs from the following providers:
Add the IDs to the Circle Developer Console:
You must ensure the ID settings for your app and the Circle Developer Console always match. If you only edit or delete IDs set on the identity provider side:
For more, see Authentication Methods.
Once you have configured the social provider IDs, you must set up
redirectedURI
, which corresponds to the loginConfigs
within the Web SDK.
During the local development phase, testing redirects for Facebook can be conducted using localhost. Google requires an HTTPS domain for redirects.
deviceId
in a POST
request to the /users/social/token
endpoint.import { initiateUserControlledWalletsClient } from '@circle-fin/user-controlled-wallets'
const circleUserSdk = initiateUserControlledWalletsClient({
apiKey: '<your-api-key>',
})
const response = await circleUserSdk.createDeviceTokenForSocialLogin({
deviceId: 'your device id',
})
Copy deviceToken
and deviceEncryptionKey
from the response and enter them
into the sample app.
{
deviceToken: string
deviceEncryptionKey: string
otpToken?: string // For email authentication method only
}
On the sample app, select Login with Google or Login with Facebook.
This takes you through the social login flow and corresponds to the SDK
method performLogin
.
If calling performLogin
doesn't return a response, check the following:
getDeviceId
.Consider wrapping the initialization process in a context hook instead of the
useEffect
hook so you can correctly capture the SDK response. Put the
context provider in the root component of the web application:
import { createContext, ReactNode, useCallback, useContext, useEffect, useMemo, useState } from 'react'
import { W3SSdk } from '@circle-fin/w3s-pw-web-sdk'
import { EmailLoginResult, Error, SocialLoginResult } from '@circle-fin/w3s-pw-web-sdk/dist/src/types'
let webSdk: W3SSdk
const Sdk = createContext<{ sdk: W3SSdk | undefined }>({
sdk: undefined,
})
const getConfig = () => ({
appSettings: { appId: process.env.NEXT_PUBLIC_CIRCLE_APP_ID || '' },
loginConfigs: {
deviceToken: localStorage.getItem('deviceToken') || '',
deviceEncryptionKey: localStorage.getItem('deviceEncryptionKey') || '',
otpToken: localStorage.getItem('otpToken') || '',
facebook: {
appId: process.env.NEXT_PUBLIC_FACEBOOK_AUTH_CLIENT_ID || '',
redirectUri: window.location.origin,
},
google: {
clientId: process.env.NEXT_PUBLIC_GOOGLE_AUTH_CLIENT_ID || '',
redirectUri: window.location.origin,
},
},
})
const initializeSdk = (
onLoginComplete: (error: Error | undefined, result: SocialLoginResult | EmailLoginResult | undefined) => void
) => {
return new W3SSdk(getConfig(), onLoginComplete)
}
export const useSdk = () => useContext(Sdk)
interface SdkProviderProps {
children: ReactNode
}
export const SdkProvider = ({ children }: SdkProviderProps): JSX.Element => {
const [sdk, setSdk] = useState<W3SSdk | undefined>(webSdk)
const onLoginComplete = useCallback(
(error: Error | undefined, result: SocialLoginResult | EmailLoginResult | undefined) => {
if (error) {
console.log(error)
} else {
console.log(result)
}
},
[]
)
useEffect(() => {
const sdk = initializeSdk(onLoginComplete)
if (sdk) {
webSdk = sdk
setSdk(webSdk)
}
}, [onLoginComplete])
const contextValues = useMemo(() => ({ sdk }), [sdk])
return <Sdk.Provider value={contextValues}>{children}</Sdk.Provider>
}
After a successful login, you are redirected back to the main page of this sample app. The "Execute Challenge" section is now visible.
Select Execute Challenge.
Both encryptionKey
and userToken
are pre-populated since these parameters
are required for the next step, which is to initialize the user.
The sample app pre-populates the encryptionKey
and userToken
for you.
During the actual development, the client-side SDK returns userId
,
userToken
, encryptionKey
, refreshToken
, and OAuthInfo
to you.
userToken
copied from the previous step in a POST
request to the
/user/initialize
endpoint.challengeId
from the response and enter it into the sample app.To create an SCA wallet, provide a Testnet blockchain such as ETH-SEPOLIA, MATIC-AMOY, and AVAX-FUJI.
The following code samples show how to create an SCA wallet on Amoy and the response.
const response = await circleUserSdk.createUserPinWithWallets({
userToken: '<USER_TOKEN>',
accountType: 'SCA',
blockchains: ['MATIC-AMOY'],
})
{
"data": {
"challengeId": "0d1b5f41-1381-50af-983b-f54691415158"
}
}
The following code samples show how to create an EOA wallet on Solana and the response.
const response = await circleUserSdk.createUserPinWithWallets({
userToken: '<USER_TOKEN>',
accountType: 'EOA',
blockchains: ['SOL-DEVNET'],
})
{
"data": {
"challengeId": "0d1b5f41-1381-50af-983b-f54691415158"
}
}
To execute a challenge during actual implementation, you must call the Web SDK
API execute
with the challengeId
returned from Circle. Also, make sure you
have an active userToken
, encryptionKey
for any challenge executions.
Once you have created a wallet in the sample app, you can check the user and wallet status.
To check the user's account status:
userToken
in a GET
request to the /user
endpoint to retrieve the
status of the user’s account.const response = await circleUserSdk.getUserStatus({
userToken: '<USER_TOKEN>',
})
{
"data": {
"id": "2f1dcb5e-312a-4b15-8240-abeffc0e3463",
"status": "ENABLED",
"createDate": "2023-07-26T15:27:32Z",
"pinStatus": "ENABLED",
"pinDetails": {
"failedAttempts": 0
},
"securityQuestionStatus": "ENABLED",
"securityQuestionDetails": {
"failedAttempts": 0
}
}
}
To check the status of the user’s new wallet.
userToken
in a GET
request to the /wallets
endpoint to retrieve
the user’s new wallet.const response = await circleUserSdk.listWallets({
userToken: '<USER_TOKEN>',
})
{
"data": {
"wallets": [
{
"id": "01899cf2-d415-7052-a207-f9862157e546",
"state": "LIVE",
"walletSetId": "01899cf2-d407-7f89-b4d9-84d63573f138",
"custodyType": "ENDUSER",
"userId": "2f1dcb5e-312a-4b15-8240-abeffc0e3463",
"address": "0x075e62c80e55d024cfd8fd4e3d1184834461db57",
"addressIndex": 0,
"blockchain": "MATIC-AMOY",
"accountType": "SCA",
"updateDate": "2023-07-28T14:41:47Z",
"createDate": "2023-07-28T14:41:47Z"
}
]
}
}
{
"data": {
"wallets": [
{
"id": "8a79c80b-4d4f-4032-971a-8bb9f9b0254f",
"state": "LIVE",
"walletSetId": "c43221d3-9db1-4cbf-8b18-e1dcae16b55d",
"custodyType": "ENDUSER",
"userId": "d8c8f832-5d4f-4123-9a7f-60120c2da5f0",
"address": "8UFfxP3zzSeqdkZ5iLTmUGzpHPRGnydZ1Vnq5GkzKTep",
"addressIndex": 0,
"blockchain": "SOL-DEVNET",
"accountType": "EOA",
"updateDate": "2023-07-28T14:43:48Z",
"createDate": "2023-07-28T14:43:48Z"
}
]
}
}
You can also view the User ID, Auth Method, and Wallet status on the Circle Developer Console: