Issue with setting up client to automatically upload wallet address, resolved with correction of dataset.

16 replies
Last updated: May 26, 2022
hello - I’m trying to set up a client to automatically upload the wallet address of users login in at the page. I’m not getting any errors at all - but it’s still not working. Nonetheless, I am still able to add documents from the schema.js, so I don’t think it’s a connection issue but rather CORS or the token.
AI Update

It sounds like you're trying to write data from the browser but hitting a permissions issue. Even though you're not seeing errors, this is often a sign that the write operation is silently failing due to authentication or CORS issues. Here's what's likely happening and how to fix it:

The Core Issue: Write Tokens in Frontend Code

Based on what you're describing, you probably have a Sanity client configured in your frontend code that's trying to create documents with wallet addresses. The most common issue is that write tokens should never be used directly in client-side code for security reasons.

When you say you can add documents from schema.js, that's likely happening in a server-side context (like during development or through the Studio), which is why it works. But browser-based writes need a different approach.

The Right Solution: Server-Side Endpoint

Instead of writing directly from the browser, you should:

  1. Create a server-side API endpoint (using Next.js API routes, serverless functions, or similar)
  2. Send the wallet address from your frontend to this endpoint
  3. Use a write token on the server to create the Sanity document

Here's a quick example with Next.js:

// pages/api/save-wallet.js (server-side)
import { createClient } from '@sanity/client'

const client = createClient({
  projectId: 'your-project-id',
  dataset: 'your-dataset',
  token: process.env.SANITY_WRITE_TOKEN, // Store this in env variables
  apiVersion: '2024-01-01',
  useCdn: false
})

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' })
  }

  const { walletAddress } = req.body

  try {
    const result = await client.create({
      _type: 'userWallet', // or whatever your schema type is
      walletAddress: walletAddress,
      timestamp: new Date().toISOString()
    })
    
    res.status(200).json({ success: true, id: result._id })
  } catch (error) {
    res.status(500).json({ error: error.message })
  }
}

Then from your frontend:

// Frontend code
async function saveWallet(walletAddress) {
  const response = await fetch('/api/save-wallet', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ walletAddress })
  })
  
  const data = await response.json()
  console.log(data) // Check for errors here
}

Alternative: Sanity Functions

If you're looking for an even more integrated solution, consider using Sanity Functions, which are serverless functions that run within Sanity's infrastructure. This eliminates the need for external hosting and provides better security out of the box.

About CORS

CORS typically isn't the issue for write operations—it's more about authentication. However, if you do need to configure CORS for your Sanity project (for read operations), you can do this in your project settings at manage.sanity.io.

Token Setup

Make sure you have a robot token with write permissions created in your Sanity Manage dashboard (under API settings), and store it as an environment variable like SANITY_WRITE_TOKEN that's only accessible server-side.

The key takeaway: never expose write tokens in frontend code. Always proxy write operations through a server-side endpoint where you can safely use your token and validate the data before writing to Sanity.

Here’s the code for the client: import sanityClient from ‘@sanity/client’
export const client = sanityClient({
projectId: ‘1d0wbsuk’,
dataset: ‘production’,
apiVersion: ‘2022-05-19’,
token: ‘token code blah blah’,
useCdn: true,
ignoreBrowserTokenWarning: true,
})
useEffect(() => { if (!address) return

; (async () => {
const userDoc = {
_type: ‘users’,
_id: address,
userName: ‘Unnamed’,
walletAddress: address,
}

const result = await client.createIfNotExists(userDoc)
})()
}, [address])
Do you mean to have a semicolon before
(async () …
or is it meant to be a colon
:
Currently it is a
;
user Y
it was meant to be a ; according to the tutorial I follow (it’s pretty weird but that’s what it said to do), but I just removed it completely and it didn’t work either. If I change it to a colon it would ask me to add an expression.
Hmm, maybe you could post the tutorial and what part of it, and I’ll try to take a look over the weekend, I am heading out here shortly but I’ll do my best
user Y
would it be better the repo of the tutorial? https://github.com/CleverProgrammers/opensea-blockchain-youtube
Sure, Post both
https://youtu.be/x3eRXeMB-4k?t=2818 I started it from the moment he started to set up the client. He sent it to a file called lib
Ok, thanks I’ll take a look and follow up 🙇‍♂️
Awesome! Thank you so much
user Y
Hey
user Y
hope you’re doing well! Got a chance to check on this? 😁
Hello! Can anyone check on this thread to see what might be happening? Thanks! 🙇‍♂️
Sorry I missed this Aisen, we were a bit busy with the Structured Content conference and I forgot to follow up. Looking into this today
user Y
I was actually able to see what was wrong: I was using the wrong dataset 🤦‍♂️. So it was in fact working, but was sending it to a dataset called production instead of another one.
Ahh, we have all been there! Sorry for the delay anyway, but glad you got it resolved!! 👍

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?