Can not verify signature for commit due to invalid signature string when using Coinbase Smart Wallet

Hi, I encountered an issue when trying to make mutation with Coinbase Smart Wallet.

The error thrown is as follow:

  {"error":"Can not verify signature for commit bagcqcerahsfrazlqhkf24arkmujhzcesgsv5nwgchhrupmdylmt5amxswbzq to stream k2t6wzhkhabz1sdy28cfzy1niwdej1anze020pzap6ur6l32kui61hyyhro8zj which has controller DID did:pkh:eip155:84532:0x5e165d772b940178966a7ed155b99050dffbec40: invalid signature string (argument=\"signature\", value=\"0x000000000000000000000000ca11bde05977b3631167028862be2a173976ca110000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000028000000000000000000000000000000000000000000000000000000000000001e482ad56cb0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000ba5ed0c6aa8c49038f819e587e2633c4a9f428a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e43ffba36f0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004024a02452ba731ad67f5510ad5daf632c689485a6296a310c69f702b57fa091d972031cb82784f2fb7d73bf41269dcafa280a335e569a5f8f36d52258b218e98e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000001700000000000000000000000000000000000000000000000000000000000000016072f5600a5f28264cbaaede083d456467e942329f038df080eaf60fed2bcee87b0917975318c1b3bea219a4fdcf3333a9f473a37f2c9326b23b3c4ae1685f7a0000000000000000000000000000000000000000000000000000000000000025f198086b2db17256731bc456673b96bcef23f51d1fbacdd7c4379ef65465572f1d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a226d6150583363643742783441714e4f6f486470496331504366614b574c677276766d76426378756c315a45222c226f726967696e223a2268747470733a2f2f6b6579732e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d000000000000000000000000000000000000000000006492649264926492649264926492649264926492649264926492649264926492\", code=INVALID_ARGUMENT, version=bytes/5.7.0)"}

After connecting Coinbase Smart Wallet, I am able to create Ceramic session for the wallet as well. The error only happens when I tried to submit mutation.

For more context, I am using Thirdweb SDK to handle login options. Metamask wallet, Coinbase EOA wallet and Thirdweb embedded wallet (MPC) work fine.

I am not sure if I should handle smart wallet differently or which part went wrong.

I appreciate any help or suggestion thanks!

The code below is how I handle DID session:

/**
 * Checks localStorage for a stored DID Session. If one is found we authenticate it, otherwise we create a new one.
 * @returns Promise<DID-Session> - The User's authenticated sesion.
 */
export const authenticateCeramic = async (
  ceramic: CeramicClient,
  compose: ComposeClient,
  provider: any,
  onDone?: () => void,
) => {
  const processedProvider = processProvider(provider);
  authenticateEthPKH(ceramic, compose, processedProvider, onDone);
};

const authenticateEthPKH = async (
  ceramic: CeramicClient,
  compose: ComposeClient,
  provider: any,
  onDone?: () => void,
) => {
  const sessionStr = localStorage.getItem(CERAMIC_SESSION_KEY); // for production you will want a better place than localStorage for your sessions.
  let session;

  if (sessionStr) {
    session = await DIDSession.fromSession(sessionStr);
  }

  if (!session || (session.hasSession && session.isExpired)) {
    /** If provider isn't passed we use window.ethereum */
    if (!provider) {
      if (window.ethereum) {
        console.log("in authenticateCeramic func: You need to pass the provider as an argument in the `authenticateCeramic()` function. We will be using window.ethereum by default.");
        provider = window.ethereum;
      } else {
        console.error("ERROR in authenticateCeramic func: no provider args passed and no window.ethereum found.");
        return false;
      }
    }

    // We enable the ethereum provider to get the user's addresses.
    // request ethereum accounts.
    const addresses = await provider.enable({
      method: "eth_requestAccounts",
    });
    const accountId = await getAccountId(provider, addresses[0]);
    const authMethod = await EthereumWebAuth.getAuthMethod(provider, accountId);
    /**
     * Create DIDSession & provide capabilities for resources that we want to access.
     * @NOTE: The specific resources (ComposeDB data models) are provided through
     * "compose.resources" below.
     */
    session = await DIDSession.authorize(authMethod, {
      // resources: [`ceramic://*`],
      resources: compose.resources,
      expiresInSecs: threeMonths
    });
    console.log({ session }, session.serialize())
    // Set the session in localStorage.
    localStorage.setItem(CERAMIC_SESSION_KEY, session.serialize());
  }

  // Set our Ceramic DID to be our session DID.
  ceramic.did = session.did;
  compose.setDID(session.did);

  if (onDone) {
    onDone();
  }
  return;
};


const processProvider = (signer: any) => {
  const provider = signer?.provider;

  provider.enable = async () => [await signer.getAddress()];

  provider.request = async (payload: any) => {
    if (payload.method === "personal_sign") {
      const message = payload.params[0];

      if (/^(0x)?[0-9A-Fa-f]+$/i.test(message)) {
        const bufferMessage = Buffer.from(
          message.startsWith("0x") ? message.slice(2) : message,
          "hex"
        );
        return signer.signMessage(bufferMessage);
      }

      return signer.signMessage(message);
    }

    return provider.send(payload.method, payload.params || []);
  };

  return provider;
};

Ceramic does not currently support smart wallets. You can see some writing on our long-term plans to support them here: Smart account support

1 Like

I see! Thanks for answering my question!