> ## Documentation Index
> Fetch the complete documentation index at: https://circle-devdocs-test-ai-codegen-component.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Your First Wallet with Social Logins

> Use API requests and Circle's sample app to create a user-controlled wallet with social logins

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](/wallets/user-controlled/create-your-first-wallet-with-email).

This quickstart uses 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](/api-reference).

You can create both Smart Contract Accounts (SCA) and Externally Owned Accounts
(EOA) wallets. To learn more, see the [Account Type](/wallets/account-types)
guide.

## Prerequisites

Before you begin:

1. Create or sign in to your
   [Circle Developer Console](https://console.circle.com/) account.
2. [Generate an API Key](/w3s/circle-developer-account#creating-a-developer-services-api-key).
3. Complete the
   [Authentication Methods](/wallets/user-controlled/authentication-methods)
   configurations before you set up the sample app.

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](http://pw-auth-example.circle.com/) on web or set it up
locally.

<Note>
  If you want to test in the iOS or Android environment, you can check our
  Github repo for [iOS sample
  app](https://github.com/circlefin/w3s-ios-sample-app-wallets) and [Android
  sample app](https://github.com/circlefin/w3s-android-sample-app-wallets).
</Note>

## Step 1. Configure sample app

1. Obtain an App ID. Either:

* From the Circle Developer Console, navigate to **Wallets > User Controlled >
  Configurator** and copy **App ID**.
* Send a `GET` request to the `/config/entity` endpoint and copy the `appId`
  from the response body.

2. Add the App ID to the sample app.

<Note>
  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`](/wallets/user-controlled/web-sdk#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.
</Note>

<Frame>
  <img src="https://mintcdn.com/circle-devdocs-test-ai-codegen-component/SJLeV2p3IVpxs9EY/w3s/images/ucw-cyfwwsl-sampleapp01.png?fit=max&auto=format&n=SJLeV2p3IVpxs9EY&q=85&s=cdbe330646fc0aa7e53f7f661eaf7b2e" width="480" height="744" data-path="w3s/images/ucw-cyfwwsl-sampleapp01.png" />
</Frame>

<Warning>
  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.
</Warning>

## Step 2. Obtain IDs from social providers

Obtain IDs from the following providers:

* **Google** has a dedicated Client ID for Web, iOS, and Android platforms. See
  the Google doc:
  [Get your Google API client ID](https://developers.google.com/identity/oauth2/web/guides/get-google-api-clientid).
* **Facebook** has an App ID. See the Facebook doc:
  [Facebook App Development](https://developers.facebook.com/docs/development).
* **Apple** has a Bundle ID for iOS, and a Service ID for Web and Android
  platforms. See the Apple doc:
  [Register an App ID](https://developer.apple.com/help/account/manage-identifiers/register-an-app-id/).

Add the IDs to the Circle Developer Console:

1. From the sidebar, navigate to **Wallets > User Controlled > Configurator**.
2. Select **Authentication Methods > Social Logins**.
3. From **Social Logins**, enter the IDs required for your app:
   * **Google**: Client ID for Android, iOS, or Web.
   * **Apple**: Bundle ID for iOS or Service ID for Android Web.
   * **Facebook**: App ID.

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:

* If your user is logged out, they will not be able to log back in even if their
  user token is active.
* If your user is logged in, they will remain logged in if their user token is
  active. When their user token expires in over 14 days, they will be logged out
  and will not be able to log back in.

For more, see
[Authentication Methods](/wallets/user-controlled/authentication-methods).

## Step 3. Set up social provider details

Once you have configured the social provider IDs, you must set up
`redirectedURI`, which corresponds to the `loginConfigs` within the Web SDK.

* For Google or Facebook, you must set the relevant URL domain or else redirects
  will be blocked by the provider.
* For Apple, Firebase is used for URL redirection. Firebase configuration must
  be properly set to carry out the Apple login flow. For setup instructions, see
  the Firebase doc:
  [Authenticate Using Apple](https://firebase.google.com/docs/auth/ios/apple).

<Frame>
  <img src="https://mintcdn.com/circle-devdocs-test-ai-codegen-component/lDxw4V0UksMNkicA/w3s/images/ucw-cyfwwsl-socialgoogle01.png?fit=max&auto=format&n=lDxw4V0UksMNkicA&q=85&s=957d91c2956d86478f3dafa1bbcc4764" width="512" height="406" data-path="w3s/images/ucw-cyfwwsl-socialgoogle01.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/circle-devdocs-test-ai-codegen-component/lDxw4V0UksMNkicA/w3s/images/ucw-cyfwwsl-socialfb01.png?fit=max&auto=format&n=lDxw4V0UksMNkicA&q=85&s=4972cc906f447d632e72a59a5ca5c687" width="512" height="405" data-path="w3s/images/ucw-cyfwwsl-socialfb01.png" />
</Frame>

<Warning>
  During the local development phase, testing redirects for Facebook can be
  conducted using localhost. Google requires an HTTPS domain for redirects.
</Warning>

## Step 4. Perform social login

1. Once the SDK setup is done, include your API key and `deviceId` in a `POST`
   request to the `/users/social/token` endpoint.

<CodeGroup>
  ```node Node.Js SDK theme={null}
  import { initiateUserControlledWalletsClient } from "@circle-fin/user-controlled-wallets";

  const circleUserSdk = initiateUserControlledWalletsClient({
    apiKey: "<your-api-key>",
  });

  const response = await circleUserSdk.createDeviceTokenForSocialLogin({
    deviceId: "your device id",
  });
  ```

  ```text cURL theme={null}
  curl --location 'https://api.circle.com/v1/w3s/users/social/token' \
  --header 'Content-Type: application/json' \
  --header `Authorization: Bearer ${your api key}` \
  --data '{
      "idempotencyKey": "9cd14a55-c31e-48cf-8bde-8b13767a4544",
      "deviceId": "your device id"
  }'
  ```
</CodeGroup>

2. Copy `deviceToken` and `deviceEncryptionKey` from the response and enter them
   into the sample app.

   ```Text Response Body theme={null}
   {
     deviceToken: string
     deviceEncryptionKey: string
     otpToken?: string // For email authentication method only
   }
   ```

   <Frame>
     <img src="https://mintcdn.com/circle-devdocs-test-ai-codegen-component/SJLeV2p3IVpxs9EY/w3s/images/ucw-cyfwwsl-sampleapp02.png?fit=max&auto=format&n=SJLeV2p3IVpxs9EY&q=85&s=30b646ef9abe62e85b6985c1fa1c7940" width="480" height="744" data-path="w3s/images/ucw-cyfwwsl-sampleapp02.png" />
   </Frame>

3. 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`.

   <Frame>
     <img src="https://mintcdn.com/circle-devdocs-test-ai-codegen-component/lDxw4V0UksMNkicA/w3s/images/ucw-cyfwwsl-socialgoogle01.png?fit=max&auto=format&n=lDxw4V0UksMNkicA&q=85&s=957d91c2956d86478f3dafa1bbcc4764" width="512" height="406" data-path="w3s/images/ucw-cyfwwsl-socialgoogle01.png" />
   </Frame>

   <Frame>
     <img src="https://mintcdn.com/circle-devdocs-test-ai-codegen-component/lDxw4V0UksMNkicA/w3s/images/ucw-cyfwwsl-socialgoogle02.png?fit=max&auto=format&n=lDxw4V0UksMNkicA&q=85&s=d67f872590c5ae8dedb2bd8d6e78cce1" width="1112" height="384" data-path="w3s/images/ucw-cyfwwsl-socialgoogle02.png" />
   </Frame>

   If calling `performLogin` doesn't return a response, check the following:

   * The identity provider credentials in the SDK and DevConsole are correct.
   * Confirm that the steps of the SDK initialization are complete, including
     calling `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:

```typescript Typescript theme={null}
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>
}
```

4. After a successful login, you are redirected back to the main page of this
   sample app. The "Execute Challenge" section is now visible.

   <Frame>
     <img src="https://mintcdn.com/circle-devdocs-test-ai-codegen-component/lDxw4V0UksMNkicA/w3s/images/ucw-cyfwwsl-sampleapp03_copy_1.png?fit=max&auto=format&n=lDxw4V0UksMNkicA&q=85&s=09e6fe342aa2d0c9c037d6abed0c0e57" width="361" height="668" data-path="w3s/images/ucw-cyfwwsl-sampleapp03_copy_1.png" />
   </Frame>

5. 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.

   <Frame>
     <img src="https://mintcdn.com/circle-devdocs-test-ai-codegen-component/SJLeV2p3IVpxs9EY/w3s/images/ucw-cyfwwsl-executechallenge01.png?fit=max&auto=format&n=SJLeV2p3IVpxs9EY&q=85&s=f17821db22b9ab289f1cd2211304d7a9" width="480" height="500" data-path="w3s/images/ucw-cyfwwsl-executechallenge01.png" />
   </Frame>

<Note>
  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.
</Note>

## Step 5. Initialize user and acquire challenge ID

1. Include `userToken` copied from the previous step in a `POST` request to the
   `/user/initialize` endpoint.
2. Copy `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.

### Amoy example

The following code samples show how to create an SCA wallet on Amoy and the
response.

<CodeGroup>
  ```javascript Node.js SDK theme={null}
  const response = await circleUserSdk.createUserPinWithWallets({
    userToken: "<USER_TOKEN>",
    accountType: "SCA",
    blockchains: ["MATIC-AMOY"],
  });
  ```

  ```coffeescript Python SDK theme={null}
  # create an api instance
  api_instance = user_controlled_wallets.UsersAndPinsApi(client)
  try:
      request = user_controlled_wallets.SetPinAndInitWalletRequest.from_dict({"accountType": 'SCA', "blockchains": ['MATIC-AMOY'], "idempotencyKey": str(uuid.uuid4()) })
      response = api_instance.create_user_with_pin_challenge("<USER_TOKEN>", request)
      print(response)
  except user_controlled_wallets.ApiException as e:
      print("Exception when calling UsersAndPinsApi->create_user_with_pin_challenge: %s\n" % e)
  ```

  ```curl cURL theme={null}
  curl --request POST \
       --url 'https://api.circle.com/v1/w3s/user/initialize' \
       --header 'accept: application/json' \
       --header 'content-type: application/json' \
       --header 'authorization: Bearer <API_KEY>' \
       --header 'X-User-Token: <USER_TOKEN>' \
       --data '
  {
  "idempotencyKey": "49e3f455-60a2-4b5e-9e9e-9400b86e5f34",
  "accountType": "SCA",
  "blockchains": [
      "MATIC-MUMBAI"
    ]
  }
  '
  ```
</CodeGroup>

```json Response Body theme={null}
{
  "data": {
    "challengeId": "0d1b5f41-1381-50af-983b-f54691415158"
  }
}
```

### Solana example

The following code samples show how to create an EOA wallet on Solana and the
response.

<CodeGroup>
  ```javascript Node.js SDK theme={null}
  const response = await circleUserSdk.createUserPinWithWallets({
    userToken: "<USER_TOKEN>",
    accountType: "EOA",
    blockchains: ["SOL-DEVNET"],
  });
  ```

  ```coffeescript Python SDK theme={null}
  # create an api instance
  api_instance = user_controlled_wallets.UsersAndPinsApi(client)
  try:
      request = user_controlled_wallets.SetPinAndInitWalletRequest.from_dict({"accountType": 'EOA', "blockchains": ['SOL-DEVNET'], "idempotencyKey": str(uuid.uuid4()) })
      response = api_instance.create_user_with_pin_challenge("<USER_TOKEN>", request)
      print(response)
  except user_controlled_wallets.ApiException as e:
      print("Exception when calling UsersAndPinsApi->create_user_with_pin_challenge: %s\n" % e)
  ```

  ```curl cURL theme={null}
  curl --request POST \
       --url 'https://api.circle.com/v1/w3s/user/initialize' \
       --header 'accept: application/json' \
       --header 'content-type: application/json' \
       --header 'authorization: Bearer <API_KEY>' \
       --header 'X-User-Token: <USER_TOKEN>' \
       --data '
  {
  "idempotencyKey": "a6f4c8d2-33b1-43b0-8a46-5b14efe063d8",
  "accountType": "EOA",
  "blockchains": [
      "SOL-DEVNET"
    ]
  }
  '
  ```
</CodeGroup>

```json Response Body theme={null}
{
  "data": {
    "challengeId": "0d1b5f41-1381-50af-983b-f54691415158"
  }
}
```

## Step 6. Create wallet

1. Paste the Challenge ID copied from the previous step into the sample app, and
   select **Execute**.
2. An “Execute Successful” message is displayed on the sample app. A web3 wallet
   is created for you users!

<Note>
  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.
</Note>

## Step 7. Check user and wallet status

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:

* Include `userToken` in a `GET` request to the `/user` endpoint to retrieve the
  status of the user’s account.

<CodeGroup>
  ```javascript Node.js SDK theme={null}
  const response = await circleUserSdk.getUserStatus({
    userToken: "<USER_TOKEN>",
  });
  ```

  ```coffeescript Python SDK theme={null}
  # create an api instance
  api_instance = user_controlled_wallets.UsersAndPinsApi(client)
  # get user by token
  try:
      response = api_instance.get_user_by_token("<USER_TOKEN>")
      print(response)
  except user_controlled_wallets.ApiException as e:
      print("Exception when calling UsersAndPinsApi->get_user_by_token: %s\n" % e)
  ```

  ```curl cURL theme={null}
  curl --request GET \
       --url 'https://api.circle.com/v1/w3s/user' \
       --header 'accept: application/json' \
       --header 'content-type: application/json' \
       --header 'authorization: Bearer <API_KEY>' \
       --header 'X-User-Token: <USER_TOKEN>'
  ```
</CodeGroup>

```json Response Body theme={null}
{
  "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.

* Include `userToken` in a `GET` request to the `/wallets` endpoint to retrieve
  the user’s new wallet.

<CodeGroup>
  ```javascript Node.js SDK theme={null}
  const response = await circleUserSdk.listWallets({
    userToken: "<USER_TOKEN>",
  });
  ```

  ```coffeescript Python SDK theme={null}
  # create an api instance
  api_instance = user_controlled_wallets.WalletsApi(client)
  # get user token
  try:
      response = api_instance.list_wallets("<USER_TOKEN>")
      print(response)
  except user_controlled_wallets.ApiException as e:
      print("Exception when calling WalletsApi->list_wallets: %s\n" % e)
  ```

  ```curl Curl theme={null}
  curl --request GET \
       --url 'https://api.circle.com/v1/w3s/wallets' \
       --header 'accept: application/json' \
       --header 'content-type: application/json' \
       --header 'authorization: Bearer <API_KEY>' \
       --header 'X-User-Token: <USER_TOKEN>'
  ```
</CodeGroup>

### Amoy sample response

```json Response Body theme={null}
{
  "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"
      }
    ]
  }
}
```

### Solana sample response

```json Response Body theme={null}
{
  "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](https://console.circle.com/):

1. From the Wallets section on the sidebar, select **User Controlled > Users**.
2. Select your user from the row. The wallet address is displayed.
