Data modeling
Learn how to create your Patchwork metadata schemas
Writing schemas
Patchwork data modeling is akin to designing a database schema. You provide fields and their corresponding types that your data will adhere to. We currently have 20 different field types you can use in your schemas, ranging from booleans to integers to strings and more.
Importantly, because the Patchwork metadata standard uses some complex structure packing to be as storage-efficient as possible, we recommend using our PDK to bootstrap your contract. When using our PDK, schemas can be modeled in simple JSON and our codegen will translate it into a valid Patchwork metadata schema.
The following PDK schema outlines a contract that stores rating scores, where each minted NFT has 2 metadata fields: one for the rater, and one for the rating.
PDK translates this into the following Patchwork721 schema, along with the necessary packing and unpacking logic.
Note the use of Patchwork’s MetadataSchemaEntry
above and the 8 parameters passed to it. Each parameter describes a special piece of information about the field—from its permissions to its content length (single, fixed-size array, etc.) to its visibility—and also includes the necessary info needed for Patchwork to unpack the data from its stored form.
Here’s the specification for MetadataSchemaEntry
:
Looking again at the rating
field code from the Ratings.sol example, this maps to the following assertion:
My “rating” field has an ID of
1
(these are zero-indexed), permission ID of0
, is auint8
type, has only1
field entry/count per record, is publiclyvisible
, is in my second storage slot (again, zero-indexed), has no offset, and has a key ofrating
.
Again, if you use PDK, you don’t need to worry too much about the details here as this code is all automatically generated for you from your JSON schema.
Field types
There are 20 available field types to use in your schemas:
Almost all of these are self-explanatory and map directly to Solidity types. The literef
type is the outlier: this type represents a reference to a Patchwork Fragment. These saved references are referred to as LiteRefs and follow a special packing scheme for hyper-efficient storage.
Dynamic and fixed-length arrays
By default, your fields will have a length of 1, meaning they only hold one piece of information per field record. If you want to store more than one item per field (i.e. arrays), use the arrayLength
key in your schema. Setting arrayLength
to 0 turns the field into a dynamic array, setting it to 1 asserts a length of 1 (equivalent to leaving it unset), and any number higher than one turns the field into a fixed-length array of that size.
For example, the following field spec documents 2 fields. The first is a dynamic-length array that can grow unboundedly, and the second is a fixed-length array that can contain 3 items.
The field type string
is a dynamic field and will not be packed with other fixed-length values.
Field permissions
When fields have a permissionID, addresses with permission grants will also be able to write to these fields on an individual basis.
The function setPermissions
on a Patchwork721 provides a bitfield of “allows” for an address. For example, to allow writing from 0xabcd to fields 1 and 4, which would be 1001 in binary (indicating a 1 or “allow” for position 1 and position 4) or 9 in base 10
To convert from permissionId to a stored value, use 1 << (permissionId - 1)
making sure to add all of the converted permission IDs for the complete value to set.