schema.proto¶
This file defines the protocol between relays and clients. It is orthogonal to the store registry and other smart contracts.
Messages must be prefixed with their acompanying encoding number as a single byte. encoding.txt defines the number for each message.
Furthermore, we expect only one message per write/binary frame. This means no buffering of multiple messages into a single write. The protocol offers repeated fields where approriate for higher throughput. A suggested transport is WebSocket over HTTPS but the protocol is agnostic, as long as it can handle binary data and keeps the framing intact.
For upgrades there exists a VERSION file in the root of the repository. The VERSION is a single unsigned integer, incremented for each change. The client and relay must agree on the VERSION before starting the protocol. In the case of WebSocket, the VERSION can be compared via the URL. The relay must close the connection if the VERSION isn't supported.
As of this version, the protocol is grouped into 2 categories: Events, which define the content of a Store, and Request/Response methods to exchange information.
StoreManifest¶
First genisis message of a store. Has to be the first message that is written and can only be written once. Use UpdateManifest to make changes.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
The event_id is a unique identifier for an event. Currently it's 32 bytes of random data. It also functions as a nonce for The events signature. The global identifier of an Item should also include the store_token_id. hash(store_token_id:signature) might suffice then with a smaller nonce. |
||
store_token_id |
The NFT Token ID used in StoreReg.registerStore(). Checkout will ownerOf() this to determine the addr for PurchaseFactory. |
||
domain |
Website URL of the store TODO: might change this to metdata inside the NFT URL. |
||
published_tag_id |
the system tag used to list active items |
UpdateManifest¶
Used to update the store manifest. The Field enum determines the field to be updated and the value to be used.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
field |
Defines the field to be updated and determines the value to be used. |
||
string |
value |
||
tag_id |
value |
See event_id for details |
|
erc20_addr |
value |
20 bytes |
CreateItem¶
Creates an item in the store.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
price |
decimal number as a string. numbers need to be always formatted to 2 decimal places. the demcimal place must use a dot ('.') as the separator. |
||
metadata |
should be valid JSON TODO: make a json schmea with minimal/required fields |
UpdateItem¶
UpdateItem changes the price or metadata of an item. Follows the same pattern as UpdateManifest.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
item_id |
the event_id of the CreateItem event |
||
field |
|||
price |
value |
decimal number. See CreateItem for formatting. |
|
metadata |
value |
CreateTag¶
Creates a tag in the store. These can be used to group items into categories. There are also a couple of system-level tags, like published. Thse are used to filter items in the store.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
name |
AddToTag¶
Adds an item to a tag. TODO: might change this to the Update* pattern.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
tag_id |
|||
item_id |
RemoveFromTag¶
Removes an item from a tag. TODO: might change this to the Update* pattern.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
tag_id |
|||
item_id |
RenameTag¶
Renames a tag. TODO: might change this to the Update* pattern.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
tag_id |
|||
name |
DeleteTag¶
Deletes a tag. TODO: might change this to the Update* pattern.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
tag_id |
ChangeStock¶
ChangeStock is used to update the stock of on or more items. Created by the relay after a cart has been paied for.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
item_ids |
repeated |
length needs to match the length of the diff field |
|
diffs |
repeated |
||
cart_id |
(optional) only set by the relay. signals payment completion after a CommitCartRequest |
||
tx_hash |
NewKeyCard¶
created by the relay when a user enrolls a key card
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
user_wallet_addr |
|||
card_public_key |
CreateCart¶
CreateCart is used to create a new cart.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
ChangeCart¶
ChangeCart is used to add or remove items from a cart.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
cart_id |
|||
item_id |
|||
quantity |
CartFinalized¶
Created by the relay after a CommitCartRequest. It signals that a cart is about to be payed and can not be changed anymore.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
cart_id |
|||
purchase_addr |
the address the user needs to send the funds to |
||
erc20_addr |
(optional) copied from CommitCartRequest |
||
sub_total |
|||
sales_tax |
|||
total |
= subtotal + sales_tax |
||
total_in_crypto |
The exact amount to transfer to the purchase_address. bigint as string. |
CartAbandoned¶
Either created by a relay for a carts that haven't been payed in time. Or by a clerk, for eg. when the customer steps back from the purchase. This frees up the items locked up in the finalized cart.
Field |
Type |
Label |
Description |
---|---|---|---|
event_id |
See StoreManifest for details |
||
cart_id |
Event¶
Event is the transport wrapper for a single Event.
For signatures we use https://eips.ethereum.org/EIPS/eip-712. The structured data definition are specified in typedData.json. The KeyCard keypair is used to sign or verify the data. The Set of all valid keys is all NewKeyCard events plus the Relays assigned on the StoreReg smart contract.
Special care must be taken for Events with optional and union fields. Specifically these are UpdateManifest, UpdateItem and ChangeStock. Some implementations of eth_signTypedData are fine with null fields, while others aren't. Therefore, the structured data specification needs to be pruned from fields that are not set.
Field |
Type |
Label |
Description |
---|---|---|---|
signature |
|||
store_manifest |
union |
||
update_manifest |
union |
||
create_item |
union |
||
update_item |
union |
||
create_tag |
union |
||
add_to_tag |
union |
||
remove_from_tag |
union |
||
rename_tag |
union |
||
delete_tag |
union |
||
create_cart |
union |
||
change_cart |
union |
||
cart_finalized |
union |
||
cart_abandoned |
union |
||
change_stock |
union |
||
new_key_card |
union |
AuthenticateRequest¶
Initiates the challenge/response protocol.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
See PingRequest for details |
||
public_key |
of their keyCard |
AuthenticateResponse¶
Returns an error if the public key is not an enrolled KeyCard. or a challenge to be signed by the KeyCard.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
error |
|||
challenge |
ChallengeSolvedRequest¶
Completes authentication by supplying the signature over the challenge.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
signature |
ChallengeSolvedResponse¶
No error means the user is authenticated.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
error |
CommitCartRequest¶
Initiate check out of a cart
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
cart_id |
|||
erc20_addr |
emtpy/unset means vanilla ETH |
CommitCartResponse¶
Returns an error if the cart is already finalized. No error blocks further changes to a cart and starts the payment process. TODO: we might change the payload in this to an Event for longevity.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
error |
|||
cart_finalized_id |
GetBlobUploadURLRequest¶
Get an URL to upload a blob to. This exists for future-proofing the protocol and reduce stress on the websocket connection.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
GetBlobUploadURLResponse¶
Returns a single-use URL to upload a blob to. The HTTP response will contain the blob's IPFS path.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
error |
|||
url |
EventWriteRequest¶
Used by the Client to write a single event to the store.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
event |
EventWriteResponse¶
Might return an error if the event or its signature is invalid. If no error is returned, the new_store_hash is the hash of the store with the new event applied. The event_sequence_no is the index of the event in the stores log.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
error |
|||
new_store_hash |
|||
event_sequence_no |
SyncStatusRequest¶
Sent by the relay to signal the number of unpushed events.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
unpushed_events |
SyncStatusResponse¶
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
error |
EventPushRequest¶
Used by the relay to push events to the client. Will not sent more events until the client has acknowledged the last batch.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
events |
repeated |
EventPushResponse¶
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
error |
PingRequest¶
Sent by the relay to check for the clients liveness. The client needs to respond with a PingResponse. The relay will close the connection if the client doesn't respond 3 times.
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
16 bytes, chosen by the sender but should be random. Used to match the response to the request. |
PingResponse¶
Field |
Type |
Label |
Description |
---|---|---|---|
request_id |
|||
error |
Error¶
Field |
Type |
Label |
Description |
---|---|---|---|
code |
TODO: make a list of error codes, maybe enum |
||
message |
UpdateItem.ItemField¶
Name |
Number |
Description |
---|---|---|
ITEM_FIELD_UNSPECIFIED |
0 |
|
ITEM_FIELD_PRICE |
1 |
|
ITEM_FIELD_METADATA |
2 |
UpdateManifest.ManifestField¶
for now we assume the owner can't be changed
Name |
Number |
Description |
---|---|---|
MANIFEST_FIELD_UNSPECIFIED |
0 |
needed as a side-effect of what protobuf calls "open enums" |
MANIFEST_FIELD_DOMAIN |
1 |
uses value:3 (type string) |
MANIFEST_FIELD_PUBLISHED_TAG |
2 |
uses value:4 (type event_id) |
MANIFEST_FIELD_ADD_ERC20 |
3 |
add uses value:5 (addrress) |
MANIFEST_FIELD_REMOVE_ERC20 |
4 |
uses value:5 (address) |
Scalar Value Types¶
double¶
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
double |
double |
double |
float |
float64 |
double |
float |
Float |
float¶
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
float |
float |
float |
float |
float32 |
float |
float |
Float |
int32¶
Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
int32 |
int32 |
int |
int |
int32 |
int |
integer |
Bignum or Fixnum (as required) |
int64¶
Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
int64 |
int64 |
long |
int/long |
int64 |
long |
integer/string |
Bignum |
uint32¶
Uses variable-length encoding.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
uint32 |
uint32 |
int |
int/long |
uint32 |
uint |
integer |
Bignum or Fixnum (as required) |
uint64¶
Uses variable-length encoding.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
uint64 |
uint64 |
long |
int/long |
uint64 |
ulong |
integer/string |
Bignum or Fixnum (as required) |
sint32¶
Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
sint32 |
int32 |
int |
int |
int32 |
int |
integer |
Bignum or Fixnum (as required) |
sint64¶
Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
sint64 |
int64 |
long |
int/long |
int64 |
long |
integer/string |
Bignum |
fixed32¶
Always four bytes. More efficient than uint32 if values are often greater than 2^28.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
fixed32 |
uint32 |
int |
int |
uint32 |
uint |
integer |
Bignum or Fixnum (as required) |
fixed64¶
Always eight bytes. More efficient than uint64 if values are often greater than 2^56.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
fixed64 |
uint64 |
long |
int/long |
uint64 |
ulong |
integer/string |
Bignum |
sfixed32¶
Always four bytes.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
sfixed32 |
int32 |
int |
int |
int32 |
int |
integer |
Bignum or Fixnum (as required) |
sfixed64¶
Always eight bytes.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
sfixed64 |
int64 |
long |
int/long |
int64 |
long |
integer/string |
Bignum |
bool¶
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
bool |
bool |
boolean |
boolean |
bool |
bool |
boolean |
TrueClass/FalseClass |
string¶
A string must always contain UTF-8 encoded or 7-bit ASCII text.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
string |
string |
String |
str/unicode |
string |
string |
string |
String (UTF-8) |
bytes¶
May contain any arbitrary sequence of bytes.
.proto Type |
C++ |
Java |
Python |
Go |
C# |
PHP |
Ruby |
---|---|---|---|---|---|---|---|
bytes |
string |
ByteString |
str |
[]byte |
ByteString |
string |
String (ASCII-8BIT) |