Skip to main content

Remote Attachment Content Type

Status Status

Remote attachments of any size can be sent using the RemoteAttachmentCodec and a storage provider.

Open for feedback

You are welcome to provide feedback on by commenting on the Remote Attachment Content Type XIP Proposal.

Configure content type

In some SDK's the AttachmentCodec is already included in the SDK. If not, you can install the package using the following command:

In the javascript SDK you need to import this package first.

npm i @xmtp/content-type-remote-attachment

After importing the package you can register the codec.

import {
ContentTypeAttachment,
AttachmentCodec,
RemoteAttachmentCodec,
ContentTypeRemoteAttachment,
} from "@xmtp/content-type-remote-attachment";
// Create the XMTP client
const xmtp = await Client.create(signer, { env: "dev" });
xmtp.registerCodec(new AttachmentCodec());
xmtp.registerCodec(new RemoteAttachmentCodec());

Send a remote attachment

Load the file, in this example im using a web browser to load the file.

//image is the uploaded event.target.files[0];
const data = await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
if (reader.result instanceof ArrayBuffer) {
resolve(reader.result);
} else {
reject(new Error("Not an ArrayBuffer"));
}
};
reader.readAsArrayBuffer(image);
});

Create the attachment object

// Local file details
const attachment = {
filename: image?.name,
mimeType: image?.type,
data: new Uint8Array(data),
};

Use the RemoteAttachmentCodec.encodeEncrypted to encrypt the attachment:

const encryptedEncoded = await RemoteAttachmentCodec.encodeEncrypted(
attachment,
new AttachmentCodec(),
);

Upload the encrypted attachment anywhere where it will be accessible via an HTTPS GET request. For example, you can use web3.storage:

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`;

Create a remote attachment. Now that you have a url, you can create a RemoteAttachment.

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:

await conversation.send(remoteAttachment, {
contentType: ContentTypeRemoteAttachment,
});

Receive, decode, and decrypt a remote attachment

Now that you can receive a remote attachment, you need a way to receive a remote attachment. For example:

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]

Once you have the attachment object created, you can also create a preview for what to show in a message input before sending:

const objectURL = URL.createObjectURL(
new Blob([Buffer.from(attachment.data)], {
type: attachment.mimeType,
}),
);

const img = document.createElement("img");
img.src = objectURL;
img.title = attachment.filename;
````

Was the information on this page helpful?
powered by XMTP