diff --git a/dist/generated/qrcode_data_pb.js b/dist/generated/qrcode_data_pb.js
index 95cd91e08297da23cfe2b6084e66ad51e1afd4da..5349e36e18de696a3d726d5a8e29603f5b780fc1 100644
--- a/dist/generated/qrcode_data_pb.js
+++ b/dist/generated/qrcode_data_pb.js
@@ -755,6 +755,707 @@ $root.vereign = (function () {
                 };
                 return Recipients_V1;
             })();
+            qrcode_data.IpfsContentData_V1 = (function () {
+                /**
+                 * Properties of an IpfsContentData_V1.
+                 * @memberof vereign.protobuf.qrcode_data
+                 * @interface IIpfsContentData_V1
+                 * @property {string|null} [cid] IpfsContentData_V1 cid
+                 * @property {string|null} [key] IpfsContentData_V1 key
+                 * @property {string|null} [head] IpfsContentData_V1 head
+                 */
+                /**
+                 * Constructs a new IpfsContentData_V1.
+                 * @memberof vereign.protobuf.qrcode_data
+                 * @classdesc Represents an IpfsContentData_V1.
+                 * @implements IIpfsContentData_V1
+                 * @constructor
+                 * @param {vereign.protobuf.qrcode_data.IIpfsContentData_V1=} [properties] Properties to set
+                 */
+                function IpfsContentData_V1(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+                /**
+                 * IpfsContentData_V1 cid.
+                 * @member {string} cid
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @instance
+                 */
+                IpfsContentData_V1.prototype.cid = "";
+                /**
+                 * IpfsContentData_V1 key.
+                 * @member {string} key
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @instance
+                 */
+                IpfsContentData_V1.prototype.key = "";
+                /**
+                 * IpfsContentData_V1 head.
+                 * @member {string} head
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @instance
+                 */
+                IpfsContentData_V1.prototype.head = "";
+                /**
+                 * Creates a new IpfsContentData_V1 instance using the specified properties.
+                 * @function create
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IIpfsContentData_V1=} [properties] Properties to set
+                 * @returns {vereign.protobuf.qrcode_data.IpfsContentData_V1} IpfsContentData_V1 instance
+                 */
+                IpfsContentData_V1.create = function create(properties) {
+                    return new IpfsContentData_V1(properties);
+                };
+                /**
+                 * Encodes the specified IpfsContentData_V1 message. Does not implicitly {@link vereign.protobuf.qrcode_data.IpfsContentData_V1.verify|verify} messages.
+                 * @function encode
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IIpfsContentData_V1} message IpfsContentData_V1 message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                IpfsContentData_V1.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.cid != null && Object.hasOwnProperty.call(message, "cid"))
+                        writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.cid);
+                    if (message.key != null && Object.hasOwnProperty.call(message, "key"))
+                        writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.key);
+                    if (message.head != null && Object.hasOwnProperty.call(message, "head"))
+                        writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.head);
+                    return writer;
+                };
+                /**
+                 * Encodes the specified IpfsContentData_V1 message, length delimited. Does not implicitly {@link vereign.protobuf.qrcode_data.IpfsContentData_V1.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IIpfsContentData_V1} message IpfsContentData_V1 message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                IpfsContentData_V1.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+                /**
+                 * Decodes an IpfsContentData_V1 message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {vereign.protobuf.qrcode_data.IpfsContentData_V1} IpfsContentData_V1
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                IpfsContentData_V1.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.vereign.protobuf.qrcode_data.IpfsContentData_V1();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                            case 1:
+                                message.cid = reader.string();
+                                break;
+                            case 2:
+                                message.key = reader.string();
+                                break;
+                            case 3:
+                                message.head = reader.string();
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                        }
+                    }
+                    return message;
+                };
+                /**
+                 * Decodes an IpfsContentData_V1 message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {vereign.protobuf.qrcode_data.IpfsContentData_V1} IpfsContentData_V1
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                IpfsContentData_V1.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+                /**
+                 * Verifies an IpfsContentData_V1 message.
+                 * @function verify
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                IpfsContentData_V1.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.cid != null && message.hasOwnProperty("cid"))
+                        if (!$util.isString(message.cid))
+                            return "cid: string expected";
+                    if (message.key != null && message.hasOwnProperty("key"))
+                        if (!$util.isString(message.key))
+                            return "key: string expected";
+                    if (message.head != null && message.hasOwnProperty("head"))
+                        if (!$util.isString(message.head))
+                            return "head: string expected";
+                    return null;
+                };
+                /**
+                 * Creates an IpfsContentData_V1 message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {vereign.protobuf.qrcode_data.IpfsContentData_V1} IpfsContentData_V1
+                 */
+                IpfsContentData_V1.fromObject = function fromObject(object) {
+                    if (object instanceof $root.vereign.protobuf.qrcode_data.IpfsContentData_V1)
+                        return object;
+                    var message = new $root.vereign.protobuf.qrcode_data.IpfsContentData_V1();
+                    if (object.cid != null)
+                        message.cid = String(object.cid);
+                    if (object.key != null)
+                        message.key = String(object.key);
+                    if (object.head != null)
+                        message.head = String(object.head);
+                    return message;
+                };
+                /**
+                 * Creates a plain object from an IpfsContentData_V1 message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IpfsContentData_V1} message IpfsContentData_V1
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                IpfsContentData_V1.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        object.cid = "";
+                        object.key = "";
+                        object.head = "";
+                    }
+                    if (message.cid != null && message.hasOwnProperty("cid"))
+                        object.cid = message.cid;
+                    if (message.key != null && message.hasOwnProperty("key"))
+                        object.key = message.key;
+                    if (message.head != null && message.hasOwnProperty("head"))
+                        object.head = message.head;
+                    return object;
+                };
+                /**
+                 * Converts this IpfsContentData_V1 to JSON.
+                 * @function toJSON
+                 * @memberof vereign.protobuf.qrcode_data.IpfsContentData_V1
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                IpfsContentData_V1.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+                return IpfsContentData_V1;
+            })();
+            qrcode_data.IpfsAttachmentData_V1 = (function () {
+                /**
+                 * Properties of an IpfsAttachmentData_V1.
+                 * @memberof vereign.protobuf.qrcode_data
+                 * @interface IIpfsAttachmentData_V1
+                 * @property {string|null} [cid] IpfsAttachmentData_V1 cid
+                 * @property {string|null} [key] IpfsAttachmentData_V1 key
+                 * @property {string|null} [contentHash] IpfsAttachmentData_V1 contentHash
+                 * @property {string|null} [head] IpfsAttachmentData_V1 head
+                 */
+                /**
+                 * Constructs a new IpfsAttachmentData_V1.
+                 * @memberof vereign.protobuf.qrcode_data
+                 * @classdesc Represents an IpfsAttachmentData_V1.
+                 * @implements IIpfsAttachmentData_V1
+                 * @constructor
+                 * @param {vereign.protobuf.qrcode_data.IIpfsAttachmentData_V1=} [properties] Properties to set
+                 */
+                function IpfsAttachmentData_V1(properties) {
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+                /**
+                 * IpfsAttachmentData_V1 cid.
+                 * @member {string} cid
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @instance
+                 */
+                IpfsAttachmentData_V1.prototype.cid = "";
+                /**
+                 * IpfsAttachmentData_V1 key.
+                 * @member {string} key
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @instance
+                 */
+                IpfsAttachmentData_V1.prototype.key = "";
+                /**
+                 * IpfsAttachmentData_V1 contentHash.
+                 * @member {string} contentHash
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @instance
+                 */
+                IpfsAttachmentData_V1.prototype.contentHash = "";
+                /**
+                 * IpfsAttachmentData_V1 head.
+                 * @member {string} head
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @instance
+                 */
+                IpfsAttachmentData_V1.prototype.head = "";
+                /**
+                 * Creates a new IpfsAttachmentData_V1 instance using the specified properties.
+                 * @function create
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IIpfsAttachmentData_V1=} [properties] Properties to set
+                 * @returns {vereign.protobuf.qrcode_data.IpfsAttachmentData_V1} IpfsAttachmentData_V1 instance
+                 */
+                IpfsAttachmentData_V1.create = function create(properties) {
+                    return new IpfsAttachmentData_V1(properties);
+                };
+                /**
+                 * Encodes the specified IpfsAttachmentData_V1 message. Does not implicitly {@link vereign.protobuf.qrcode_data.IpfsAttachmentData_V1.verify|verify} messages.
+                 * @function encode
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IIpfsAttachmentData_V1} message IpfsAttachmentData_V1 message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                IpfsAttachmentData_V1.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.cid != null && Object.hasOwnProperty.call(message, "cid"))
+                        writer.uint32(/* id 1, wireType 2 =*/ 10).string(message.cid);
+                    if (message.key != null && Object.hasOwnProperty.call(message, "key"))
+                        writer.uint32(/* id 2, wireType 2 =*/ 18).string(message.key);
+                    if (message.contentHash != null && Object.hasOwnProperty.call(message, "contentHash"))
+                        writer.uint32(/* id 3, wireType 2 =*/ 26).string(message.contentHash);
+                    if (message.head != null && Object.hasOwnProperty.call(message, "head"))
+                        writer.uint32(/* id 4, wireType 2 =*/ 34).string(message.head);
+                    return writer;
+                };
+                /**
+                 * Encodes the specified IpfsAttachmentData_V1 message, length delimited. Does not implicitly {@link vereign.protobuf.qrcode_data.IpfsAttachmentData_V1.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IIpfsAttachmentData_V1} message IpfsAttachmentData_V1 message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                IpfsAttachmentData_V1.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+                /**
+                 * Decodes an IpfsAttachmentData_V1 message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {vereign.protobuf.qrcode_data.IpfsAttachmentData_V1} IpfsAttachmentData_V1
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                IpfsAttachmentData_V1.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.vereign.protobuf.qrcode_data.IpfsAttachmentData_V1();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                            case 1:
+                                message.cid = reader.string();
+                                break;
+                            case 2:
+                                message.key = reader.string();
+                                break;
+                            case 3:
+                                message.contentHash = reader.string();
+                                break;
+                            case 4:
+                                message.head = reader.string();
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                        }
+                    }
+                    return message;
+                };
+                /**
+                 * Decodes an IpfsAttachmentData_V1 message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {vereign.protobuf.qrcode_data.IpfsAttachmentData_V1} IpfsAttachmentData_V1
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                IpfsAttachmentData_V1.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+                /**
+                 * Verifies an IpfsAttachmentData_V1 message.
+                 * @function verify
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                IpfsAttachmentData_V1.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.cid != null && message.hasOwnProperty("cid"))
+                        if (!$util.isString(message.cid))
+                            return "cid: string expected";
+                    if (message.key != null && message.hasOwnProperty("key"))
+                        if (!$util.isString(message.key))
+                            return "key: string expected";
+                    if (message.contentHash != null && message.hasOwnProperty("contentHash"))
+                        if (!$util.isString(message.contentHash))
+                            return "contentHash: string expected";
+                    if (message.head != null && message.hasOwnProperty("head"))
+                        if (!$util.isString(message.head))
+                            return "head: string expected";
+                    return null;
+                };
+                /**
+                 * Creates an IpfsAttachmentData_V1 message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {vereign.protobuf.qrcode_data.IpfsAttachmentData_V1} IpfsAttachmentData_V1
+                 */
+                IpfsAttachmentData_V1.fromObject = function fromObject(object) {
+                    if (object instanceof $root.vereign.protobuf.qrcode_data.IpfsAttachmentData_V1)
+                        return object;
+                    var message = new $root.vereign.protobuf.qrcode_data.IpfsAttachmentData_V1();
+                    if (object.cid != null)
+                        message.cid = String(object.cid);
+                    if (object.key != null)
+                        message.key = String(object.key);
+                    if (object.contentHash != null)
+                        message.contentHash = String(object.contentHash);
+                    if (object.head != null)
+                        message.head = String(object.head);
+                    return message;
+                };
+                /**
+                 * Creates a plain object from an IpfsAttachmentData_V1 message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IpfsAttachmentData_V1} message IpfsAttachmentData_V1
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                IpfsAttachmentData_V1.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.defaults) {
+                        object.cid = "";
+                        object.key = "";
+                        object.contentHash = "";
+                        object.head = "";
+                    }
+                    if (message.cid != null && message.hasOwnProperty("cid"))
+                        object.cid = message.cid;
+                    if (message.key != null && message.hasOwnProperty("key"))
+                        object.key = message.key;
+                    if (message.contentHash != null && message.hasOwnProperty("contentHash"))
+                        object.contentHash = message.contentHash;
+                    if (message.head != null && message.hasOwnProperty("head"))
+                        object.head = message.head;
+                    return object;
+                };
+                /**
+                 * Converts this IpfsAttachmentData_V1 to JSON.
+                 * @function toJSON
+                 * @memberof vereign.protobuf.qrcode_data.IpfsAttachmentData_V1
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                IpfsAttachmentData_V1.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+                return IpfsAttachmentData_V1;
+            })();
+            qrcode_data.IpfsData_V1 = (function () {
+                /**
+                 * Properties of an IpfsData_V1.
+                 * @memberof vereign.protobuf.qrcode_data
+                 * @interface IIpfsData_V1
+                 * @property {vereign.protobuf.qrcode_data.IIpfsContentData_V1|null} [plaintText] IpfsData_V1 plaintText
+                 * @property {vereign.protobuf.qrcode_data.IIpfsContentData_V1|null} [html] IpfsData_V1 html
+                 * @property {Array.<vereign.protobuf.qrcode_data.IIpfsAttachmentData_V1>|null} [attachments] IpfsData_V1 attachments
+                 */
+                /**
+                 * Constructs a new IpfsData_V1.
+                 * @memberof vereign.protobuf.qrcode_data
+                 * @classdesc Represents an IpfsData_V1.
+                 * @implements IIpfsData_V1
+                 * @constructor
+                 * @param {vereign.protobuf.qrcode_data.IIpfsData_V1=} [properties] Properties to set
+                 */
+                function IpfsData_V1(properties) {
+                    this.attachments = [];
+                    if (properties)
+                        for (var keys = Object.keys(properties), i = 0; i < keys.length; ++i)
+                            if (properties[keys[i]] != null)
+                                this[keys[i]] = properties[keys[i]];
+                }
+                /**
+                 * IpfsData_V1 plaintText.
+                 * @member {vereign.protobuf.qrcode_data.IIpfsContentData_V1|null|undefined} plaintText
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @instance
+                 */
+                IpfsData_V1.prototype.plaintText = null;
+                /**
+                 * IpfsData_V1 html.
+                 * @member {vereign.protobuf.qrcode_data.IIpfsContentData_V1|null|undefined} html
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @instance
+                 */
+                IpfsData_V1.prototype.html = null;
+                /**
+                 * IpfsData_V1 attachments.
+                 * @member {Array.<vereign.protobuf.qrcode_data.IIpfsAttachmentData_V1>} attachments
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @instance
+                 */
+                IpfsData_V1.prototype.attachments = $util.emptyArray;
+                /**
+                 * Creates a new IpfsData_V1 instance using the specified properties.
+                 * @function create
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IIpfsData_V1=} [properties] Properties to set
+                 * @returns {vereign.protobuf.qrcode_data.IpfsData_V1} IpfsData_V1 instance
+                 */
+                IpfsData_V1.create = function create(properties) {
+                    return new IpfsData_V1(properties);
+                };
+                /**
+                 * Encodes the specified IpfsData_V1 message. Does not implicitly {@link vereign.protobuf.qrcode_data.IpfsData_V1.verify|verify} messages.
+                 * @function encode
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IIpfsData_V1} message IpfsData_V1 message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                IpfsData_V1.encode = function encode(message, writer) {
+                    if (!writer)
+                        writer = $Writer.create();
+                    if (message.plaintText != null && Object.hasOwnProperty.call(message, "plaintText"))
+                        $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.encode(message.plaintText, writer.uint32(/* id 1, wireType 2 =*/ 10).fork()).ldelim();
+                    if (message.html != null && Object.hasOwnProperty.call(message, "html"))
+                        $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.encode(message.html, writer.uint32(/* id 2, wireType 2 =*/ 18).fork()).ldelim();
+                    if (message.attachments != null && message.attachments.length)
+                        for (var i = 0; i < message.attachments.length; ++i)
+                            $root.vereign.protobuf.qrcode_data.IpfsAttachmentData_V1.encode(message.attachments[i], writer.uint32(/* id 3, wireType 2 =*/ 26).fork()).ldelim();
+                    return writer;
+                };
+                /**
+                 * Encodes the specified IpfsData_V1 message, length delimited. Does not implicitly {@link vereign.protobuf.qrcode_data.IpfsData_V1.verify|verify} messages.
+                 * @function encodeDelimited
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IIpfsData_V1} message IpfsData_V1 message or plain object to encode
+                 * @param {$protobuf.Writer} [writer] Writer to encode to
+                 * @returns {$protobuf.Writer} Writer
+                 */
+                IpfsData_V1.encodeDelimited = function encodeDelimited(message, writer) {
+                    return this.encode(message, writer).ldelim();
+                };
+                /**
+                 * Decodes an IpfsData_V1 message from the specified reader or buffer.
+                 * @function decode
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @param {number} [length] Message length if known beforehand
+                 * @returns {vereign.protobuf.qrcode_data.IpfsData_V1} IpfsData_V1
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                IpfsData_V1.decode = function decode(reader, length) {
+                    if (!(reader instanceof $Reader))
+                        reader = $Reader.create(reader);
+                    var end = length === undefined ? reader.len : reader.pos + length, message = new $root.vereign.protobuf.qrcode_data.IpfsData_V1();
+                    while (reader.pos < end) {
+                        var tag = reader.uint32();
+                        switch (tag >>> 3) {
+                            case 1:
+                                message.plaintText = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.decode(reader, reader.uint32());
+                                break;
+                            case 2:
+                                message.html = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.decode(reader, reader.uint32());
+                                break;
+                            case 3:
+                                if (!(message.attachments && message.attachments.length))
+                                    message.attachments = [];
+                                message.attachments.push($root.vereign.protobuf.qrcode_data.IpfsAttachmentData_V1.decode(reader, reader.uint32()));
+                                break;
+                            default:
+                                reader.skipType(tag & 7);
+                                break;
+                        }
+                    }
+                    return message;
+                };
+                /**
+                 * Decodes an IpfsData_V1 message from the specified reader or buffer, length delimited.
+                 * @function decodeDelimited
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @static
+                 * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
+                 * @returns {vereign.protobuf.qrcode_data.IpfsData_V1} IpfsData_V1
+                 * @throws {Error} If the payload is not a reader or valid buffer
+                 * @throws {$protobuf.util.ProtocolError} If required fields are missing
+                 */
+                IpfsData_V1.decodeDelimited = function decodeDelimited(reader) {
+                    if (!(reader instanceof $Reader))
+                        reader = new $Reader(reader);
+                    return this.decode(reader, reader.uint32());
+                };
+                /**
+                 * Verifies an IpfsData_V1 message.
+                 * @function verify
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @static
+                 * @param {Object.<string,*>} message Plain object to verify
+                 * @returns {string|null} `null` if valid, otherwise the reason why it is not
+                 */
+                IpfsData_V1.verify = function verify(message) {
+                    if (typeof message !== "object" || message === null)
+                        return "object expected";
+                    if (message.plaintText != null && message.hasOwnProperty("plaintText")) {
+                        var error = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.verify(message.plaintText);
+                        if (error)
+                            return "plaintText." + error;
+                    }
+                    if (message.html != null && message.hasOwnProperty("html")) {
+                        var error = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.verify(message.html);
+                        if (error)
+                            return "html." + error;
+                    }
+                    if (message.attachments != null && message.hasOwnProperty("attachments")) {
+                        if (!Array.isArray(message.attachments))
+                            return "attachments: array expected";
+                        for (var i = 0; i < message.attachments.length; ++i) {
+                            var error = $root.vereign.protobuf.qrcode_data.IpfsAttachmentData_V1.verify(message.attachments[i]);
+                            if (error)
+                                return "attachments." + error;
+                        }
+                    }
+                    return null;
+                };
+                /**
+                 * Creates an IpfsData_V1 message from a plain object. Also converts values to their respective internal types.
+                 * @function fromObject
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @static
+                 * @param {Object.<string,*>} object Plain object
+                 * @returns {vereign.protobuf.qrcode_data.IpfsData_V1} IpfsData_V1
+                 */
+                IpfsData_V1.fromObject = function fromObject(object) {
+                    if (object instanceof $root.vereign.protobuf.qrcode_data.IpfsData_V1)
+                        return object;
+                    var message = new $root.vereign.protobuf.qrcode_data.IpfsData_V1();
+                    if (object.plaintText != null) {
+                        if (typeof object.plaintText !== "object")
+                            throw TypeError(".vereign.protobuf.qrcode_data.IpfsData_V1.plaintText: object expected");
+                        message.plaintText = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.fromObject(object.plaintText);
+                    }
+                    if (object.html != null) {
+                        if (typeof object.html !== "object")
+                            throw TypeError(".vereign.protobuf.qrcode_data.IpfsData_V1.html: object expected");
+                        message.html = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.fromObject(object.html);
+                    }
+                    if (object.attachments) {
+                        if (!Array.isArray(object.attachments))
+                            throw TypeError(".vereign.protobuf.qrcode_data.IpfsData_V1.attachments: array expected");
+                        message.attachments = [];
+                        for (var i = 0; i < object.attachments.length; ++i) {
+                            if (typeof object.attachments[i] !== "object")
+                                throw TypeError(".vereign.protobuf.qrcode_data.IpfsData_V1.attachments: object expected");
+                            message.attachments[i] = $root.vereign.protobuf.qrcode_data.IpfsAttachmentData_V1.fromObject(object.attachments[i]);
+                        }
+                    }
+                    return message;
+                };
+                /**
+                 * Creates a plain object from an IpfsData_V1 message. Also converts values to other types if specified.
+                 * @function toObject
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @static
+                 * @param {vereign.protobuf.qrcode_data.IpfsData_V1} message IpfsData_V1
+                 * @param {$protobuf.IConversionOptions} [options] Conversion options
+                 * @returns {Object.<string,*>} Plain object
+                 */
+                IpfsData_V1.toObject = function toObject(message, options) {
+                    if (!options)
+                        options = {};
+                    var object = {};
+                    if (options.arrays || options.defaults)
+                        object.attachments = [];
+                    if (options.defaults) {
+                        object.plaintText = null;
+                        object.html = null;
+                    }
+                    if (message.plaintText != null && message.hasOwnProperty("plaintText"))
+                        object.plaintText = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.toObject(message.plaintText, options);
+                    if (message.html != null && message.hasOwnProperty("html"))
+                        object.html = $root.vereign.protobuf.qrcode_data.IpfsContentData_V1.toObject(message.html, options);
+                    if (message.attachments && message.attachments.length) {
+                        object.attachments = [];
+                        for (var j = 0; j < message.attachments.length; ++j)
+                            object.attachments[j] = $root.vereign.protobuf.qrcode_data.IpfsAttachmentData_V1.toObject(message.attachments[j], options);
+                    }
+                    return object;
+                };
+                /**
+                 * Converts this IpfsData_V1 to JSON.
+                 * @function toJSON
+                 * @memberof vereign.protobuf.qrcode_data.IpfsData_V1
+                 * @instance
+                 * @returns {Object.<string,*>} JSON object
+                 */
+                IpfsData_V1.prototype.toJSON = function toJSON() {
+                    return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
+                };
+                return IpfsData_V1;
+            })();
             qrcode_data.EmailData_V1 = (function () {
                 /**
                  * Properties of an EmailData_V1.
@@ -767,6 +1468,7 @@ $root.vereign = (function () {
                  * @property {vereign.protobuf.qrcode_data.IRecipients_V1|null} [recipients] EmailData_V1 recipients
                  * @property {Array.<vereign.protobuf.qrcode_data.IAttachment_V1>|null} [attachments] EmailData_V1 attachments
                  * @property {string|null} [senderPublicKeyUuid] EmailData_V1 senderPublicKeyUuid
+                 * @property {vereign.protobuf.qrcode_data.IIpfsData_V1|null} [ipfs] EmailData_V1 ipfs
                  */
                 /**
                  * Constructs a new EmailData_V1.
@@ -832,6 +1534,13 @@ $root.vereign = (function () {
                  * @instance
                  */
                 EmailData_V1.prototype.senderPublicKeyUuid = "";
+                /**
+                 * EmailData_V1 ipfs.
+                 * @member {vereign.protobuf.qrcode_data.IIpfsData_V1|null|undefined} ipfs
+                 * @memberof vereign.protobuf.qrcode_data.EmailData_V1
+                 * @instance
+                 */
+                EmailData_V1.prototype.ipfs = null;
                 /**
                  * Creates a new EmailData_V1 instance using the specified properties.
                  * @function create
@@ -870,6 +1579,8 @@ $root.vereign = (function () {
                             $root.vereign.protobuf.qrcode_data.Attachment_V1.encode(message.attachments[i], writer.uint32(/* id 6, wireType 2 =*/ 50).fork()).ldelim();
                     if (message.senderPublicKeyUuid != null && Object.hasOwnProperty.call(message, "senderPublicKeyUuid"))
                         writer.uint32(/* id 7, wireType 2 =*/ 58).string(message.senderPublicKeyUuid);
+                    if (message.ipfs != null && Object.hasOwnProperty.call(message, "ipfs"))
+                        $root.vereign.protobuf.qrcode_data.IpfsData_V1.encode(message.ipfs, writer.uint32(/* id 8, wireType 2 =*/ 66).fork()).ldelim();
                     return writer;
                 };
                 /**
@@ -925,6 +1636,9 @@ $root.vereign = (function () {
                             case 7:
                                 message.senderPublicKeyUuid = reader.string();
                                 break;
+                            case 8:
+                                message.ipfs = $root.vereign.protobuf.qrcode_data.IpfsData_V1.decode(reader, reader.uint32());
+                                break;
                             default:
                                 reader.skipType(tag & 7);
                                 break;
@@ -989,6 +1703,11 @@ $root.vereign = (function () {
                     if (message.senderPublicKeyUuid != null && message.hasOwnProperty("senderPublicKeyUuid"))
                         if (!$util.isString(message.senderPublicKeyUuid))
                             return "senderPublicKeyUuid: string expected";
+                    if (message.ipfs != null && message.hasOwnProperty("ipfs")) {
+                        var error = $root.vereign.protobuf.qrcode_data.IpfsData_V1.verify(message.ipfs);
+                        if (error)
+                            return "ipfs." + error;
+                    }
                     return null;
                 };
                 /**
@@ -1031,6 +1750,11 @@ $root.vereign = (function () {
                     }
                     if (object.senderPublicKeyUuid != null)
                         message.senderPublicKeyUuid = String(object.senderPublicKeyUuid);
+                    if (object.ipfs != null) {
+                        if (typeof object.ipfs !== "object")
+                            throw TypeError(".vereign.protobuf.qrcode_data.EmailData_V1.ipfs: object expected");
+                        message.ipfs = $root.vereign.protobuf.qrcode_data.IpfsData_V1.fromObject(object.ipfs);
+                    }
                     return message;
                 };
                 /**
@@ -1055,6 +1779,7 @@ $root.vereign = (function () {
                         object.date = "";
                         object.recipients = null;
                         object.senderPublicKeyUuid = "";
+                        object.ipfs = null;
                     }
                     if (message.statusId != null && message.hasOwnProperty("statusId"))
                         object.statusId = message.statusId;
@@ -1073,6 +1798,8 @@ $root.vereign = (function () {
                     }
                     if (message.senderPublicKeyUuid != null && message.hasOwnProperty("senderPublicKeyUuid"))
                         object.senderPublicKeyUuid = message.senderPublicKeyUuid;
+                    if (message.ipfs != null && message.hasOwnProperty("ipfs"))
+                        object.ipfs = $root.vereign.protobuf.qrcode_data.IpfsData_V1.toObject(message.ipfs, options);
                     return object;
                 };
                 /**
diff --git a/dist/types.d.ts b/dist/types.d.ts
index 77bc26610e09a7393c25e56afc81cfcd6bff3289..dd2fbf38a1276a0c8a2eec7e2327bcf340372717 100644
--- a/dist/types.d.ts
+++ b/dist/types.d.ts
@@ -11,6 +11,22 @@ export interface Attachment {
     hashAlg: string;
     signature: string;
 }
+export interface IpfsContentData {
+    cid: string;
+    key: string;
+    head: string;
+}
+export interface IpfsAttachmentData {
+    cid: string;
+    key: string;
+    contentHash: string;
+    head: string;
+}
+export interface IpfsData {
+    plaintText: IpfsContentData;
+    html: IpfsContentData;
+    attachments: Array<IpfsAttachmentData>;
+}
 export interface MessageData {
     sender: Participant;
     subject: string;
@@ -21,6 +37,7 @@ export interface MessageData {
     };
     attachments: Array<Attachment>;
     senderPublicKeyUuid: string;
+    ipfs?: IpfsData;
 }
 export interface StatusData {
     status?: StatusObject;
diff --git a/src/types.ts b/src/types.ts
index 312f3fc3b8c9ad85d496d6aedc3fceec91e72c2a..89bf1b6fa821efb086c67201a44f08120d71d9ae 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -14,6 +14,25 @@ export interface Attachment {
   signature: string;
 }
 
+export interface IpfsContentData {
+  cid: string;
+  key: string;
+  head: string;
+}
+
+export interface IpfsAttachmentData {
+  cid: string;
+  key: string;
+  contentHash: string;
+  head: string;
+}
+
+export interface IpfsData {
+  plaintText: IpfsContentData;
+  html: IpfsContentData;
+  attachments: Array<IpfsAttachmentData>;
+}
+
 export interface MessageData {
   sender: Participant;
   subject: string;
@@ -24,6 +43,7 @@ export interface MessageData {
   };
   attachments: Array<Attachment>;
   senderPublicKeyUuid: string;
+  ipfs?: IpfsData;
 }
 
 export interface StatusData {
diff --git a/vereign/protobuf/qrcode_data.proto b/vereign/protobuf/qrcode_data.proto
index 49673a46e222dea44f93c7d6df4147b490968c3b..8d9c61e7947ed6b1116cb454d91f58917dc3adbf 100644
--- a/vereign/protobuf/qrcode_data.proto
+++ b/vereign/protobuf/qrcode_data.proto
@@ -22,6 +22,25 @@ message Recipients_V1 {
   repeated Participant_V1 cc = 2;
 }
 
+message IpfsContentData_V1 {
+    string cid = 1;
+    string key = 2;
+    string head = 3;
+}
+
+message IpfsAttachmentData_V1 {
+    string cid = 1;
+    string key = 2;
+    string contentHash = 3;
+    string head = 4;
+}
+
+message IpfsData_V1 {
+  IpfsContentData_V1 plaintText = 1;
+  IpfsContentData_V1 html = 2;
+  repeated IpfsAttachmentData_V1 attachments = 3;
+}
+
 message EmailData_V1 {
   string statusId = 1;
   Participant_V1 sender = 2;
@@ -29,7 +48,8 @@ message EmailData_V1 {
   string date = 4;
   Recipients_V1 recipients = 5;
   repeated Attachment_V1 attachments = 6;
-  string senderPublicKeyUuid = 7; 
+  string senderPublicKeyUuid = 7;
+  IpfsData_V1 ipfs = 8;
 }
 
 message KeyData_V1 {