Skip to content

Mutating Entities

All entity mutations are sent as standard Ethereum transactions to a special Arkiv address. The transaction data field carries an encoded payload that describes one or more operations.

PropertyValue
Arkiv Address0x00000000000000000000000000000061726b6976
Block Time2 seconds
Transaction Value0 (no ETH transferred)

The transaction data is a 5-element array:

[
creates, // index 0
updates, // index 1
deletes, // index 2
extensions, // index 3
ownershipChanges // index 4
]

Each element is an array of operations of that type.

IndexFieldTypeDescription
0expiresInBlocksnumberceil(seconds / 2)
1contentTypestringMIME type
2payloadstringEntity content
3stringAttributes[[key, value], ...]String-typed attributes
4numberAttributes[[key, value], ...]Number-typed attributes
IndexFieldTypeDescription
0entityKeyhex string0x-prefixed entity key
1contentTypestringMIME type
2expiresInBlocksnumberceil(seconds / 2)
3payloadstringEntity content
4stringAttributes[[key, value], ...]String-typed attributes
5numberAttributes[[key, value], ...]Number-typed attributes

Each delete entry is just the entity key as a 0x-prefixed hex string.

IndexFieldTypeDescription
0entityKeyhex string0x-prefixed entity key
1expiresInBlocksnumberceil(additionalSeconds / 2)
IndexFieldTypeDescription
0entityKeyhex string0x-prefixed entity key
1newOwnerhex string0x-prefixed address of the new owner

Attributes are split into two arrays by value type:

  • String attributes[["category", "documentation"], ["version", "1.0"]]
  • Number attributes[["priority", 5], ["count", 100]]

The payload goes through four stages before inclusion in a transaction:

  1. Human-readable JSON — Start with a JSON array matching the 5-element structure.

  2. Hex-encode all leaf values — Convert every leaf to a 0x-prefixed hex string. Strings become hex-encoded UTF-8, numbers become hex-encoded integers, and 0 becomes "0x".

  3. RLP-encode — The nested hex structure is RLP-encoded into a flat byte sequence.

  4. Brotli-compress — The RLP bytes are compressed with Brotli. The output is hex-encoded with a 0x prefix.

Goal: Create an entity with payload {"message": "Hello from Arkiv"}, content type application/json, 30-day expiration, string and number attributes.

[
[
[
1296000,
"application/json",
"{\"message\":\"Hello from Arkiv\"}",
[["category", "example"], ["version", "1.0"]],
[["priority", 0], ["count", 100]]
]
],
[],
[],
[],
[]
]
[
[
[
"0x13c680",
"0x6170706c69636174696f6e2f6a736f6e",
"0x7b226d657373616765223a2248656c6c6f2066726f6d2041726b6976227d",
[
["0x63617465676f7279", "0x6578616d706c65"],
["0x76657273696f6e", "0x312e30"]
],
[
["0x7072696f72697479", "0x"],
["0x636f756e74", "0x64"]
]
]
],
[],
[],
[],
[]
]
Terminal window
rlp encode '<hex-encoded-json>'
Terminal window
echo "$RLP_HEX" | sed 's/^0x//' | xxd -r -p | brotli | xxd -p | tr -d '\n' | sed 's/^/0x/'

This final hex string is the transaction data field.

FieldValue
to0x00000000000000000000000000000061726b6976
value0
datathe Brotli-compressed hex payload
Terminal window
curl -s https://kaolin.hoodi.arkiv.network/rpc \
-H "content-type: application/json" \
-d '{
"jsonrpc":"2.0",
"id":1,
"method":"eth_sendRawTransaction",
"params":["'"$SIGNED_TX"'"]
}'
Terminal window
curl -s https://kaolin.hoodi.arkiv.network/rpc \
-H "content-type: application/json" \
-d '{
"jsonrpc":"2.0",
"id":1,
"method":"eth_getTransactionReceipt",
"params":["'"$TX_HASH"'"]
}'

The receipt’s logs contain the entity keys for each operation.

All five operation types can be combined in a single transaction:

[
[[1296000, "application/json", "{\"name\":\"Entity A\"}", [["type","alpha"]], []]],
[["0xabc...", "application/json", 2592000, "{\"name\":\"Updated B\"}", [["type","beta"]], []]],
["0xdef..."],
[["0x123...", 3888000]],
[["0x456...", "0x789..."]]
]

When parsing logs from a batch transaction, events are emitted in this order:

  1. Creates
  2. Deletes
  3. Updates