Remote Attachment Content Type
Remote attachments of any size can be sent using the RemoteAttachmentCodec and a storage provider.
Install the package
- JavaScript
npm i @xmtp/content-type-remote-attachment
Import and register
- JavaScript
// Import the codecs we're going to use
import {
  AttachmentCodec,
  RemoteAttachmentCodec,
} from "@xmtp/content-type-remote-attachment";
// Create the XMTP client
const xmtp = await Client.create(signer, { env: "dev" });
// Register the codecs. AttachmentCodec is for local attachments (<1MB)
xmtp.registerCodec(new AttachmentCodec());
//RemoteAttachmentCodec is for remote attachments (>1MB) using thirdweb storage
xmtp.registerCodec(new RemoteAttachmentCodec());
Create an attachment object
- Frontend
const arrayBuffer = await file.arrayBuffer();
// Local file details
const attachment = {
  filename: filename,
  mimeType: extname,
  data: new Uint8Array(data),
};
Encrypt the attachment
Use the RemoteAttachmentCodec.encodeEncrypted to encrypt the attachment:
- JavaScript
const encryptedEncoded = await RemoteAttachmentCodec.encodeEncrypted(
  attachment,
  new AttachmentCodec(),
);
Upload the encrypted attachment
Upload the encrypted attachment anywhere where it will be accessible via an HTTPS GET request. For example, you can use web3.storage:
- Web3 Storage
- Thirdweb
const { Web3Storage } = require("web3.storage");
class Upload {
  constructor(name, data) {
    this.name = name;
    this.data = data;
  }
  stream() {
    const self = this;
    return new ReadableStream({
      start(controller) {
        controller.enqueue(Buffer.from(self.data));
        controller.close();
      },
    });
  }
}
const upload = new Upload("uploadIdOfYourChoice", encryptedEncoded.payload);
const web3Storage = new Web3Storage({
  token: "YOURTOKENHERE",
});
const cid = await web3Storage.put([upload]);
const url = `https://${cid}.ipfs.w3s.link/uploadIdOfYourChoice`;
import { useStorageUpload } from "@thirdweb-dev/react";
const { mutateAsync: upload } = useStorageUpload();
const uploadUrl = await upload({
  //encryptedEncoded.payload.buffer is a Uint8Array
  //We need to convert it to a File to upload it to the IPFS network
  data: [new File([encryptedEncoded.payload.buffer], file.name)], // Convert Uint8Array back to File
  options: { uploadWithGatewayUrl: true, uploadWithoutDirectory: true },
});
const url = uploadUrl[0];
Create a remote attachment
Now that you have a url, you can create a RemoteAttachment.
- JavaScript
const remoteAttachment = {
  url: url,
  contentDigest: encryptedEncoded.digest,
  salt: encryptedEncoded.salt,
  nonce: encryptedEncoded.nonce,
  secret: encryptedEncoded.secret,
  scheme: "https://",
  filename: attachment.filename,
  contentLength: attachment.data.byteLength,
};
Send a remote attachment
Now that you have a remote attachment, you can send it:
- JavaScript
await conversation.send(remoteAttachment, {
  contentType: ContentTypeRemoteAttachment,
});
Download, decrypt, and decode the attachment
Now that you can receive a remote attachment, you need a way to receive a remote attachment. For example:
- JavaScript
if (message.contentType.sameAs(RemoteAttachmentContentType)) {
  const attachment = await RemoteAttachmentCodec.load(message.content, client);
}
- You now have the original attachment:
attachment.filename // => "screenshot.png"
attachment.mimeType // => "image/png",
attachment.data // => [the PNG data]
Create a preview attachment object
Once you have the attachment object created, you can also create a preview for what to show in a message input before sending:
- JavaScript
URL.createObjectURL(
    new Blob([Buffer.from(attachment.data)], {
    type: attachment.mimeType,
  }),
),