Signing - Solana

Signing with Solana - Phantom Wallet

Using the txn variable obtained from previous steps. We use the jsonToSign field and sign it as a personal signMessage using Phantom wallet.

Phantom / Solana do not allow message signatures > ~1000 bytes. To workaround this, we allow signing the SHA256 hash of the JSON in cases where payload.jsonToSign.length > 1000.

const getProvider = () => {
  if ('phantom' in window) {
    const phantomWindow = window as any;
    const provider = phantomWindow.phantom?.solana;
    if (provider?.isPhantom) {
      return provider;
    }

    window.open('https://phantom.app/', '_blank');
  }
};

const signTxn = async (context: TxContext, payload: TransactionPayload, simulate: boolean) => {
  if (!account) throw new Error('Account not found.');

  let sig = '';
  if (!simulate) {
    //Phantom has a weird error where messages must be < ~1000 bytes
    //If we are within limit, we can have user sign the JSON
    //Else, we hash the JSON and have user sign the hash

    const normalMessage = payload.jsonToSign.length < 1000;
    let message = payload.jsonToSign;
    let encodedMessage = new TextEncoder().encode(message);

    if (!normalMessage) {
      message = payload.jsonToSign;
      const sha256Message = CryptoJS.SHA256(message).toString();
      encodedMessage = new TextEncoder().encode(sha256Message);
    }

    const signedMessage = await getProvider().request({
      method: 'signMessage',
      params: {
        message: encodedMessage,
        display: 'utf8'
      }
    });
    sig = signedMessage.signature.toString('hex');
  }

  //We need to pass in solAddress manually here
  const txBody = createTxBroadcastBody(context, payload, sig, address);
  return txBody;
};

Full Snippet

Last updated