diff --git a/README.md b/README.md index a6acaf8..7ec08b9 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,765 @@ -# Valorem Trade Interfaces +# Valorem Trade API -The Valorem Trade API enables peer-to-peer, signature based, noncustodial +![Valorem Trade API](img/valorem-trade-api-banner.png) + +## Background + +The Valorem Trade API enables peer-to-peer, signature-based, noncustodial digital asset trading via low latency [gRPC](https://grpc.io/docs/what-is-grpc/introduction/) and [gRPC-web](https://github.com/grpc/grpc-web) TLS-encrypted [version 3 protocol buffer](https://protobuf.dev/programming-guides/proto3/) interfaces, with order settlement via -the [Seaport smart contracts](https://github.com/ProjectOpenSea/seaport). -This repository contains the protocol buffer definitions, example integrations, and -supporting libraries for using the Trade API. +the [Seaport smart contracts](https://github.com/ProjectOpenSea/seaport). +The complete protocol buffer definitions can be found +in [this repository](https://github.com/valorem-labs-inc/trade-interfaces). + +## Deployments + +The public endpoint for the Valorem Trade API is `https://trade.valorem.xyz`. + +## User roles + +There are two principal user roles in the Valorem Trade API: + +- **Maker**: Makers are users who sign offers in response to a request for quote. + They are responsible for having the requisite assets when a taker optionally + fills their signed offer. Makers are presently required to request access to + the maker API via the [Valorem discord](https://discord.gg/valorem). + +- **Taker**: Takers are users who request quotes from makers and optionally + execute signed offers via the Seaport smart contracts. Takers are presently + required to possess a [Valorem Access Pass](https://opensea.io/collection/valorem-access-pass) to access the API. + +These protections are in place to ensure that the API is not abused during the +early access period. + +## TLS Certificate Authority + +The Valorem Trade API uses the GoDaddy Root TLS certificate authority (CA) to +issue certificates; some protobuf clients may need to add this CA, which can be +found [here](certs/trade.valorem.xyz.pem). + +## ALPN + +The Valorem Trade API supports HTTP/2 via the `h2` ALPN protocol. + +## Keepalives and timeouts + +The Valorem Trade API sends HTTP/2 keepalives every 75 seconds and times out +after 10 seconds if a response is not received. Users of the API should use HTTP/2 +keepalives, and not issue TCP keepalives. + +## Errors and status codes + +The Valorem Trade API uses the [gRPC richer error model](https://grpc.io/docs/guides/error/#richer-error-model). +It additionally uses [standard gRPC status codes](https://grpc.github.io/grpc/core/md_doc_statuscodes.html) to +indicate the success or failure of an API call. + +This allows the client to programmatically determine the cause of an error and +take appropriate action. + +## Rate limiting + +Rate limits are applied to certain services and methods in the Valorem Trade API. +These rate limits are subject to change and are not guaranteed. Details about +any applied rate limits can be found on the service and method documentation. + +## Primitive data types + +The trade API defines some primitive data types mirroring a subset of +the [Solidity ABI](https://docs.soliditylang.org/en/latest/abi-spec.html): + +### H40 + +A 40-bit data type + +```protobuf +message H40 { + uint32 hi = 1; + // Note: lo is really a uint8, however the closest type in Protocol Buffers is uint32. Parsing needs + // to take this into consideration. + uint32 lo = 2; +} +``` + +### H96 + +A 96-bit data type + +```protobuf +message H96 { + uint64 hi = 1; + uint32 lo = 2; +} +``` + +### H128 + +A 128-bit data type + +```protobuf +message H128 { + uint64 hi = 1; + uint64 lo = 2; +} +``` + +### H160 + +A 160-bit data type + +```protobuf +message H160 { + H128 hi = 1; + uint32 lo = 2; +} +``` + +### H256 + +A 256-bit data type + +```protobuf +message H256 { + H128 hi = 1; + H128 lo = 2; +} +``` + +As well as a few utility types: + +### Empty + +An empty message type + +```protobuf +message Empty {} +``` + +### EthSignature + +An Ethereum signature. [ECDSA](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm) signatures in +Ethereum consist of three parameters: +`v`, `r` and `s`. The signature is always 65-bytes in length. + +- `r` (`bytes`): first 32 bytes of signature +- `s` (`bytes`): second 32 bytes of signature +- `v` (`bytes`): 1 byte of signature + +```protobuf +message EthSignature { + bytes r = 1; + bytes s = 2; + bytes v = 3; +} +``` + +## Seaport data types + +This section describes protobuf data types and messages used by the Trade API as +they relate to Seaport. + +**For a full reference on the Seaport smart contracts and interfaces, see +the [Seaport documentation](https://docs.opensea.io/reference/seaport-overview).** + +### ItemType + +The ItemType designates the type of item, with valid types being Ether +(or other native token for the given chain), +[ERC20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/), +[ERC721](https://ethereum.org/en/developers/docs/standards/tokens/erc-721/), +[ERC1155](https://ethereum.org/en/developers/docs/standards/tokens/erc-1155/), +ERC721 with "criteria" (explained below), and ERC1155 with criteria. + +```protobuf +enum ItemType { + NATIVE = 0; + ERC20 = 1; + ERC721 = 2; + ERC1155 = 3; + ERC721_WITH_CRITERIA = 4; + ERC1155_WITH_CRITERIA = 5; +} +``` + +### ConsiderationItem + +An item required in exchange for an offer. + +```protobuf +message ConsiderationItem { + ItemType item_type = 1; + H160 token = 2; // address + H256 identifier_or_criteria = 3; // uint256 + H256 start_amount = 4; // uint256 + H256 end_amount = 5; // uint256 + H160 recipient = 6; +} +``` + +### OfferItem + +An item offered in exchange for consideration. + +```protobuf +message OfferItem { + ItemType item_type = 1; + H160 token = 2; + H256 identifier_or_criteria = 3; + H256 start_amount = 4; + H256 end_amount = 5; // uint256 +} +``` + +- `item_type`: Designates the type of item. +- `token`: Designates the account of the item's token contract (with the null + address used for Ether or other native tokens). +- `identifier_or_criteria`: Represents either the ERC721 or ERC1155 + token identifier or, in the case of a criteria-based item type, a + merkle root composed of the valid set of token identifiers for + the item. This value will be ignored for Ether and ERC20 item types, + and can optionally be zero for criteria-based item types to allow + for any identifier. +- `start_amount`: Represents the amount of the item in question that + will be required should the order be fulfilled at the moment the + order becomes active. +- `end_amount`: Represents the amount of the item in question that + will be required should the order be fulfilled at the moment the + order expires. If this value differs from the item's `start_amount`, + the realized amount is calculated linearly based on the time elapsed + since the order became active. + +### OrderType + +Designates one of four types for the order depending on two distinct preferences: + +```protobuf +enum OrderType { + FULL_OPEN = 0; + PARTIAL_OPEN = 1; + FULL_RESTRICTED = 2; + PARTIAL_RESTRICTED = 3; +} +``` + +- `FULL` indicates that the order does not support partial fills, + whereas `PARTIAL` enables filling some fraction of the order, with the + important caveat that each item must be cleanly divisible by the supplied + fraction (i.e. no remainder after division). `OPEN` indicates that the call to + execute the order can be submitted by any account, whereas `RESTRICTED` requires + that the order either be executed by the `offerer` or the `zone` of the order, or + that a magic value indicating that the order is approved is returned upon + calling validateOrder on the zone. + +### Order + +A Seaport order. Each order contains ten key components. + +```protobuf +message Order { + H160 offerer = 1; + H160 zone = 2; + repeated OfferItem offer = 3; + repeated ConsiderationItem consideration = 4; + OrderType order_type = 5; + H256 start_time = 6; + H256 end_time = 7; + H256 zone_hash = 8; + H256 salt = 9; + H256 conduit_key = 10; +} +``` + +- `offerer`: Supplies all offered items and must either + fulfill the order personally (i.e. `msg.sender == offerer`) or approve + the order via signature (either standard 65-byte EDCSA, 64-byte + [EIP-2098](https://eips.ethereum.org/EIPS/eip-2098), + or an [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) `isValidSignature` check) or by listing the order + on-chain (i.e. calling `validate`). +- `zone`: An optional secondary account attached to the + order with two additional privileges: + - The zone may cancel orders where it is named as the zone by calling + cancel. (Note that `offerer`s can also cancel their own orders, either + individually or for all orders signed with their current counter at + once by calling `incrementCounter`). + - "Restricted" orders (as specified by the `order_type`) must either be + executed by the zone or the `offerer`, or must be approved as indicated + by a call to an `validateOrder` on the `zone`. +- `offer`: Contains an array of items that may be transferred + from the `offerer`'s account. +- `consideration`: Contains an array of items that must be received + in order to fulfill the order. It contains the same components + as an offered item, and additionally includes a recipient that will + receive each item. This array may be extended by the fulfiller on + order fulfillment as to support "tipping" (e.g. relayer or + referral payments) +- `order_type`: Indicates whether the order supports partial fills + and whether the order can be executed by any account or only by the + `offerer` or `zone`. +- `start_time`: Indicates the block timestamp at which the order + becomes active. +- `end_time`: Indicates the block timestamp at which the order expires. + This value and the `start_time` are used in conjunction with the + `start_amount` and `end_amount` of each item to derive their current amount. +- `zone_hash`: Represents an arbitrary `bytes32` value that will be + supplied to the `zone` when fulfilling restricted orders that the `zone` + can utilize when making a determination on whether to authorize the order. +- `salt`: Represents an arbitrary source of entropy for the order. +- `conduit_key`: Indicates what conduit, + if any, should be utilized as a source for token approvals when + performing transfers. By default, i.e. when `conduit_key` is set to the + zero hash, the `offerer` will grant ERC20, ERC721, and ERC1155 token + approvals to Seaport directly so that it can perform any transfers + specified by the order during fulfillment. In contrast, an `offerer` + that elects to utilize a conduit will grant token approvals to the + conduit contract corresponding to the supplied `conduit_key`, and + Seaport will then instruct that conduit to transfer the respective + tokens. + +### SignedOrder + +A signed order ready for execution via Seaport. + +```protobuf +message SignedOrder { + Order parameters = 1; + EthSignature signature = 2; +} +``` + +## API Services + +### Health + +The Valorem Trade API uses +the [gRPC health checking protocol](https://github.com/grpc/grpc/blob/master/doc/health-checking.md) +to provide a general health check endpoint, as well as endpoints for each of the services. +Health checks for each service are available via `grpc.health.v1.Health`, queryable +by passing the Valorem service name `valorem.trade.v1.`. + +### Reflection + +The Valorem Trade API uses the [gRPC reflection protocol](https://github.com/grpc/grpc/blob/master/doc/server-reflection.md) +to provide service discovery and reflection. Reflection is available +via `grpc.reflection.v1alpha.ServerReflection`. + +### Auth service + +The Authentication Service in Valorem Trade API enables users to authenticate +themselves via SIWE, and receive the necessary credentials to access the other +services provided by the API. The Auth service uses session cookies to store +authentication information. Auth sessions are backed by +cryptographically signed cookies. These cookies are generated when they’re +not found or are otherwise invalid. When a valid, known cookie is received +in a request, the session is hydrated from this cookie. These cookies are validated +server-side. This provides compatibility with both browser and +non-browser clients "out of the box." + +Non-browser clients must implement cookie storage and management themselves. + +This service supports gRPC and gRPC-web clients. + +```protobuf +service Auth { + ... +} +``` + +#### Methods + +##### `Nonce` + +Returns an [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361) nonce for the +session and invalidates any existing session. This method resets session cookie, +which is passed back on the request. + +```protobuf +rpc Nonce (Empty) returns (NonceText); +``` + +###### Unary request + +```protobuf +message Empty {} +``` + +###### Unary response + +`0 OK` + +The request was successful. + +```protobuf +message NonceText { + string nonce = 1; +} +``` + +- `nonce` (`string`): a randomized token typically chosen by the Trade API, and + used to prevent replay attacks, at least 8 alphanumeric characters UTF-8 encoded as plaintext. + +##### `Verify` + +Verifies a valid SIWE message and returns the Ethereum address of the signer. +Upon successful verification, the Auth session is updated. + +```protobuf +rpc Verify (VerifyText) returns (H160); +``` + +###### Unary request + +```protobuf +message VerifyText { + string body = 1; +} +``` + +- `body` (`string`): a JSON-encoded, signed, [EIP-191](https://eips.ethereum.org/EIPS/eip-191) signature scheme message. + The message must contain the following + string: `I accept the Valorem Terms of Service at https://app.valorem.xyz/tos and Privacy Policy at https://app.valorem.xyz/privacy` + +Example signed and JSON encoded message: + +```json +{ + "message": "app.valorem.xyz wants you to sign in with your Ethereum account:\n\n\nI accept the Valorem Terms of Service at https://app.valorem.xyz/tos and Privacy Policy at https://app.valorem.xyz/privacy\n\nURI: https://app.valorem.xyz\nVersion: 1\nChain ID: 421613\nNonce: \nIssued At: 2023-06-10T03:37:23.858Z", + "signature": "" +} +``` + +###### Unary response + +`0 OK` + +The request was successful, the response is the verified 160-bit address as an `H160`. + +```protobuf +message H160 { +} +``` + +##### `Authenticate` + +Checks if a given connection is authenticated and returns the authenticated +address for an Auth session. + +```protobuf +rpc Authenticate (Empty) returns (H160); +``` + +###### Unary request + +```protobuf +message Empty {} +``` + +###### Unary response + +`0 OK` + +The request was successful, the response is the authenticated 160-bit address as an `H160`. + +```protobuf +message H160 { +} + +``` + +### Fees + +The Fees Service in Valorem Trade API provides information about the fees which +must be paid to use the API. The Fees service uses session cookies to store +authentication, and requires authentication to access because of fee tiers for +various users. + +Non-browser clients must implement cookie storage and management themselves. + +This service supports gRPC and gRPC-web clients. + +```protobuf +service Fees { + ... +} +``` + +#### Methods + +##### `getFeeStructure` + +Returns the `FeeStructure` for a user. + +```protobuf +rpc getFeeStructure(Empty) returns (FeeStructure); +``` + +###### Unary request + +```protobuf +message Empty {} +``` + +###### Unary response + +```protobuf +message FeeStructure { + TradeFees maker = 1; + TradeFees taker = 2; + int32 clear_write_notional_bps = 3; + int32 clear_redeemed_notional_bps = 4; + int32 clear_exercise_notional_bps = 5; + H160 address = 6; +} +``` + +- `maker` (`TradeFees`): The fees for a maker. +- `taker` (`TradeFees`): The fees for a taker. +- `clear_write_notional_bps` (`int32`): A fee or rebate on notional value written via Clear expressed in basis points. +- `clear_redeemed_notional_bps` (`int32`): A fee or rebate on underlying asset notional value redeemed via Clear + expressed in basis points. +- `clear_exercise_notional_bps` (`int32`): A fee or rebate on notional value exercised via Clear expressed in basis + points. +- `address` (`H160`): The address fees must be paid to or rebates are received from. + +```protobuf +message TradeFees { + int32 notional_bps = 1; + int32 premium_bps = 2; + int32 spot_bps = 3; + int32 flat = 4; +} +``` + +- `notional_bps` (`int32`): A fee or rebate on notional value traded expressed in basis points. +- `premium_bps` (`int32`): A fee or rebate on premia or credit value traded expressed in basis points. +- `spot_bps` (`int32`): A fee or rebate on spot value traded expressed in basis points. +- `flat` (`int32`): A flat relayer fee or rebate expressed in 1e-6 USDC (dust) - used for non-valued + offers/considerations such as NFTs. + +### RFQ + +The RFQ (Request for Quote) service of the Valorem Trade API allows authenticated +takers to request quotes from makers, for those makers to respond with signed +offers, and for those traders to receive those signed offers for executing +trades on the Seaport smart contracts. It acts as a peer-to-peer signature relay. + +```protobuf +service RFQ { + ... +} +``` + +#### Fees + +Responses from the RFQ service are subject to fees. +Fees are determined by the maker and taker `FeeStructure` from the [Fees service](#fees-service). +The fees must be included in the offer as follows: + +For a long Valorem option buy: + +Two offer items, one of which is the RFQ'd option long token in the correct +quantity, the second of which is a maker fee/rebate in USDC (if any). + +Two consideration items, the USDC premia, and a taker fee/rebate in USDC +(if any). + +For a long Valorem option sell: + +Two offer items, one of which is the USDC credit, the other of which is a maker +fee in USDC (if any). + +Two consideration items, one of which is the RFQ option long token in the +correct quantity, the second of which is a taker fee in fee/rebate in USDC +(if any). + +For a short Valorem option buy: + +Two offer items, one of which is an unexercised claim for the RFQ'd option +type in the correct quantity, the second of which is the maker fee/rebate in +USDC (if any). + +Three consideration items, >= the USDC notional value at spot as quoted from +uniswap, the USDC premia, the taker fee/rebate in USDC (if any). + +For a short Valorem option sell: + +Three offer items, >= the USDC notional value at spot as quoted from uniswap, +the USDC premia, the maker fee/rebate in USDC (if any). + +Two consideration items, one of which is an unexercised claim for the RFQ'd +option type in the correct quantity, the second of which is the taker +fee/rebate in USDC (if any). + +#### Authentication and authorization + +Only authenticated and authorized users can access the RFQ service. + +#### Methods + +##### `Taker` + +Request quotes from makers via a stream of `QuoteRequest` messages and receive +a stream of `QuoteResponse` messages. + +```protobuf +rpc Taker (stream QuoteRequest) returns (stream QuoteResponse); +``` + +###### Request stream + +```protobuf +message QuoteRequest { + optional H128 ulid = 1; + optional H160 taker_address = 2; + ItemType item_type = 3; + optional H160 token_address = 4; + optional H256 identifier_or_criteria = 5; + H256 amount = 6; + Action action = 7; + optional H256 chain_id = 8; + optional H160 seaport_address = 9; +} +``` + +- `ulid` (`H128`, optional): The unique identifier for the quote request. This gets populated by the API. +- `taker_address` (`H160`, optional): The address of the taker, used to tailor an RFQ for the taker. +- `item_type` (`ItemType`): The type of item for which a quote is being requested. +- `token_address` (`H160`, optional): The token address for which a quote is being requested. +- `identifier_or_criteria` (`H256`, optional): The identifier or criteria for the item. +- `amount` (`H256`): The amount of the item. +- `action` (`Action`): The action (`BUY` or `SELL`) for the quote request. +- `chain_id` (`H256`, optional): The chain ID for the quote request. Must specify a supported chain. + Supported chains are `[42161, 421613]`. Defaults to `421613`. +- `seaport_address` (`H160`, optional): The Seaport address for the quote request, defaults + to `0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC`. + +###### Response stream + +```protobuf +message QuoteResponse { + optional H128 ulid = 1; + optional H160 maker_address = 2; + SignedOrder order = 3; + optional H256 chain_id = 4; + optional H160 seaport_address = 5; +} +``` + +- `ulid` (`H128`, optional): The unique identifier for the quote request. This must match a quote request to be received by a taker. +- `maker_address` (`H160`, optional): The address of the maker making the offer. +- `order` (`SignedOrder`): The order and signature from the maker. +- `chain_id` (`H256`, optional): The chain ID for the offer. This must match the quote request chain ID. Defaults to the quote request chain ID matched by ulid. +- `seaport_address` (`H160`, optional): The Seaport address for the offer, defaults + to `0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC`. + +##### `Maker` + +Send quotes to takers via a stream of `QuoteResponse` messages and receive a +stream of `QuoteRequest` messages. + +```protobuf +rpc Maker (stream QuoteResponse) returns (stream QuoteRequest); +``` + +###### Request stream + +```protobuf +message QuoteResponse { + optional H128 ulid = 1; + optional H160 maker_address = 2; + SignedOrder order = 3; + optional H256 chain_id = 4; + optional H160 seaport_address = 5; +} +``` + +- `ulid` (`H128`, optional): The unique identifier for the quote request. This must match a quote request to be received by a taker. +- `maker_address` (`H160`, optional): The address of the maker making the offer. +- `order` (`SignedOrder`): The order and signature from the maker. +- `chain_id` (`H256`, optional): The chain ID for the offer. This must match the quote request chain ID. Defaults to the quote request chain ID matched by ulid. +- `seaport_address` (`H160`, optional): The Seaport address for the offer, defaults + to `0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC`. + +###### Response stream + +```protobuf +message QuoteRequest { + optional H128 ulid = 1; + optional H160 taker_address = 2; + ItemType item_type = 3; + optional H160 token_address = 4; + optional H256 identifier_or_criteria = 5; + H256 amount = 6; + Action action = 7; + optional H256 chain_id = 8; + optional H160 seaport_address = 9; +} +``` + +- `ulid` (`H128`, optional): The unique identifier for the quote request. This gets populated by the API. +- `taker_address` (`H160`, optional): The address of the taker, used to tailor an RFQ for the taker. +- `item_type` (`ItemType`): The type of item for which a quote is being requested. +- `token_address` (`H160`, optional): The token address for which a quote is being requested. +- `identifier_or_criteria` (`H256`, optional): The identifier or criteria for the item. +- `amount` (`H256`): The amount of the item. +- `action` (`Action`): The action (`BUY` or `SELL`) for the quote request. +- `chain_id` (`H256`, optional): The chain ID for the quote request. Must specify a supported chain. + Supported chains are `[42161, 421613]`. Defaults to `421613`. +- `seaport_address` (`H160`, optional): The Seaport address for the quote request, defaults + to `0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC`. + +##### `WebTaker` + +Quotes from makers via a unary `QuoteRequest` message and receive a stream +of `QuoteResponse` messages for use by gRPC-web clients such as browsers. + +```protobuf +rpc WebTaker (QuoteRequest) returns (stream QuoteResponse); +``` + +###### Unary request + +```protobuf +message QuoteRequest { + optional H128 ulid = 1; + optional H160 taker_address = 2; + ItemType item_type = 3; + H160 token_address = 4; + optional H256 identifier_or_criteria = 5; + H256 amount = 6; + Action action = 7; + optional H256 chain_id = 8; + optional H160 seaport_address = 9; +} +``` + +- `ulid` (`H128`, optional): The unique identifier for the quote request. This gets populated by the API. +- `taker_address` (`H160`, optional): The address of the taker, used to tailor an RFQ for the taker. +- `item_type` (`ItemType`): The type of item for which a quote is being requested. +- `token_address` (`H160`, optional): The token address for which a quote is being requested. +- `identifier_or_criteria` (`H256`, optional): The identifier or criteria for the item. +- `amount` (`H256`): The amount of the item. +- `action` (`Action`): The action (`BUY` or `SELL`) for the quote request. +- `chain_id` (`H256`, optional): The chain ID for the quote request. Must specify a supported chain. + Supported chains are `[42161, 421613]`. Defaults to `421613`. +- `seaport_address` (`H160`, optional): The Seaport address for the quote request, defaults + to `0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC`. + +###### Response stream -Full API reference documentation is available [here](https://valorem.xyz/docs/trade-api-reference/). +```protobuf +message QuoteResponse { + optional H128 ulid = 1; + optional H160 maker_address = 2; + SignedOrder order = 3; + optional H256 chain_id = 4; + optional H160 seaport_address = 5; +} +``` -The public endpoint for the trade API is `https://trade.valorem.xyz`. +- `ulid` (`H128`, optional): The unique identifier for the quote request. This must match a quote request to be received by a taker. +- `maker_address` (`H160`, optional): The address of the maker making the offer. +- `order` (`SignedOrder`): The order and signature from the maker. +- `chain_id` (`H256`, optional): The chain ID for the offer. This must match the quote request chain ID. Defaults to the quote request chain ID matched by ulid. +- `seaport_address` (`H160`, optional): The Seaport address for the offer, defaults + to `0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC`. \ No newline at end of file diff --git a/img/valorem-trade-api-banner.png b/img/valorem-trade-api-banner.png new file mode 100644 index 0000000..ef78318 Binary files /dev/null and b/img/valorem-trade-api-banner.png differ diff --git a/proto/google/rpc/error_details.proto b/proto/google/rpc/error_details.proto new file mode 100644 index 0000000..70d6239 --- /dev/null +++ b/proto/google/rpc/error_details.proto @@ -0,0 +1,285 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc; + +import "google/protobuf/duration.proto"; + +option go_package = "google.golang.org/genproto/googleapis/rpc/errdetails;errdetails"; +option java_multiple_files = true; +option java_outer_classname = "ErrorDetailsProto"; +option java_package = "com.google.rpc"; +option objc_class_prefix = "RPC"; + +// Describes the cause of the error with structured details. +// +// Example of an error when contacting the "pubsub.googleapis.com" API when it +// is not enabled: +// +// { "reason": "API_DISABLED" +// "domain": "googleapis.com" +// "metadata": { +// "resource": "projects/123", +// "service": "pubsub.googleapis.com" +// } +// } +// +// This response indicates that the pubsub.googleapis.com API is not enabled. +// +// Example of an error that is returned when attempting to create a Spanner +// instance in a region that is out of stock: +// +// { "reason": "STOCKOUT" +// "domain": "spanner.googleapis.com", +// "metadata": { +// "availableRegions": "us-central1,us-east2" +// } +// } +message ErrorInfo { + // The reason of the error. This is a constant value that identifies the + // proximate cause of the error. Error reasons are unique within a particular + // domain of errors. This should be at most 63 characters and match a + // regular expression of `[A-Z][A-Z0-9_]+[A-Z0-9]`, which represents + // UPPER_SNAKE_CASE. + string reason = 1; + + // The logical grouping to which the "reason" belongs. The error domain + // is typically the registered service name of the tool or product that + // generates the error. Example: "pubsub.googleapis.com". If the error is + // generated by some common infrastructure, the error domain must be a + // globally unique value that identifies the infrastructure. For Google API + // infrastructure, the error domain is "googleapis.com". + string domain = 2; + + // Additional structured details about this error. + // + // Keys should match /[a-zA-Z0-9-_]/ and be limited to 64 characters in + // length. When identifying the current value of an exceeded limit, the units + // should be contained in the key, not the value. For example, rather than + // {"instanceLimit": "100/request"}, should be returned as, + // {"instanceLimitPerRequest": "100"}, if the client exceeds the number of + // instances that can be created in a single (batch) request. + map metadata = 3; +} + +// Describes when the clients can retry a failed request. Clients could ignore +// the recommendation here or retry when this information is missing from error +// responses. +// +// It's always recommended that clients should use exponential backoff when +// retrying. +// +// Clients should wait until `retry_delay` amount of time has passed since +// receiving the error response before retrying. If retrying requests also +// fail, clients should use an exponential backoff scheme to gradually increase +// the delay between retries based on `retry_delay`, until either a maximum +// number of retries have been reached or a maximum retry delay cap has been +// reached. +message RetryInfo { + // Clients should wait at least this long between retrying the same request. + google.protobuf.Duration retry_delay = 1; +} + +// Describes additional debugging info. +message DebugInfo { + // The stack trace entries indicating where the error occurred. + repeated string stack_entries = 1; + + // Additional debugging information provided by the server. + string detail = 2; +} + +// Describes how a quota check failed. +// +// For example if a daily limit was exceeded for the calling project, +// a service could respond with a QuotaFailure detail containing the project +// id and the description of the quota limit that was exceeded. If the +// calling project hasn't enabled the service in the developer console, then +// a service could respond with the project id and set `service_disabled` +// to true. +// +// Also see RetryInfo and Help types for other details about handling a +// quota failure. +message QuotaFailure { + // A message type used to describe a single quota violation. For example, a + // daily quota or a custom quota that was exceeded. + message Violation { + // The subject on which the quota check failed. + // For example, "clientip:" or "project:". + string subject = 1; + + // A description of how the quota check failed. Clients can use this + // description to find more about the quota configuration in the service's + // public documentation, or find the relevant quota limit to adjust through + // developer console. + // + // For example: "Service disabled" or "Daily Limit for read operations + // exceeded". + string description = 2; + } + + // Describes all quota violations. + repeated Violation violations = 1; +} + +// Describes what preconditions have failed. +// +// For example, if an RPC failed because it required the Terms of Service to be +// acknowledged, it could list the terms of service violation in the +// PreconditionFailure message. +message PreconditionFailure { + // A message type used to describe a single precondition failure. + message Violation { + // The type of PreconditionFailure. We recommend using a service-specific + // enum type to define the supported precondition violation subjects. For + // example, "TOS" for "Terms of Service violation". + string type = 1; + + // The subject, relative to the type, that failed. + // For example, "google.com/cloud" relative to the "TOS" type would indicate + // which terms of service is being referenced. + string subject = 2; + + // A description of how the precondition failed. Developers can use this + // description to understand how to fix the failure. + // + // For example: "Terms of service not accepted". + string description = 3; + } + + // Describes all precondition violations. + repeated Violation violations = 1; +} + +// Describes violations in a client request. This error type focuses on the +// syntactic aspects of the request. +message BadRequest { + // A message type used to describe a single bad request field. + message FieldViolation { + // A path that leads to a field in the request body. The value will be a + // sequence of dot-separated identifiers that identify a protocol buffer + // field. + // + // Consider the following: + // + // message CreateContactRequest { + // message EmailAddress { + // enum Type { + // TYPE_UNSPECIFIED = 0; + // HOME = 1; + // WORK = 2; + // } + // + // optional string email = 1; + // repeated EmailType type = 2; + // } + // + // string full_name = 1; + // repeated EmailAddress email_addresses = 2; + // } + // + // In this example, in proto `field` could take one of the following values: + // + // * `full_name` for a violation in the `full_name` value + // * `email_addresses[1].email` for a violation in the `email` field of the + // first `email_addresses` message + // * `email_addresses[3].type[2]` for a violation in the second `type` + // value in the third `email_addresses` message. + // + // In JSON, the same values are represented as: + // + // * `fullName` for a violation in the `fullName` value + // * `emailAddresses[1].email` for a violation in the `email` field of the + // first `emailAddresses` message + // * `emailAddresses[3].type[2]` for a violation in the second `type` + // value in the third `emailAddresses` message. + string field = 1; + + // A description of why the request element is bad. + string description = 2; + } + + // Describes all violations in a client request. + repeated FieldViolation field_violations = 1; +} + +// Contains metadata about the request that clients can attach when filing a bug +// or providing other forms of feedback. +message RequestInfo { + // An opaque string that should only be interpreted by the service generating + // it. For example, it can be used to identify requests in the service's logs. + string request_id = 1; + + // Any data that was used to serve this request. For example, an encrypted + // stack trace that can be sent back to the service provider for debugging. + string serving_data = 2; +} + +// Describes the resource that is being accessed. +message ResourceInfo { + // A name for the type of resource being accessed, e.g. "sql table", + // "cloud storage bucket", "file", "Google calendar"; or the type URL + // of the resource: e.g. "type.googleapis.com/google.pubsub.v1.Topic". + string resource_type = 1; + + // The name of the resource being accessed. For example, a shared calendar + // name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current + // error is + // [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED]. + string resource_name = 2; + + // The owner of the resource (optional). + // For example, "user:" or "project:". + string owner = 3; + + // Describes what error is encountered when accessing this resource. + // For example, updating a cloud project may require the `writer` permission + // on the developer console project. + string description = 4; +} + +// Provides links to documentation or for performing an out of band action. +// +// For example, if a quota check failed with an error indicating the calling +// project hasn't enabled the accessed service, this can contain a URL pointing +// directly to the right place in the developer console to flip the bit. +message Help { + // Describes a URL link. + message Link { + // Describes what the link offers. + string description = 1; + + // The URL of the link. + string url = 2; + } + + // URL(s) pointing to additional information on handling the current error. + repeated Link links = 1; +} + +// Provides a localized error message that is safe to return to the user +// which can be attached to an RPC error. +message LocalizedMessage { + // The locale used following the specification defined at + // https://www.rfc-editor.org/rfc/bcp/bcp47.txt. + // Examples are: "en-US", "fr-CH", "es-MX" + string locale = 1; + + // The localized error message in the above locale. + string message = 2; +} \ No newline at end of file diff --git a/proto/google/rpc/status.proto b/proto/google/rpc/status.proto new file mode 100644 index 0000000..5bd51aa --- /dev/null +++ b/proto/google/rpc/status.proto @@ -0,0 +1,47 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +package google.rpc; + +import "google/protobuf/any.proto"; + +option cc_enable_arenas = true; +option go_package = "google.golang.org/genproto/googleapis/rpc/status;status"; +option java_multiple_files = true; +option java_outer_classname = "StatusProto"; +option java_package = "com.google.rpc"; +option objc_class_prefix = "RPC"; + +// The `Status` type defines a logical error model that is suitable for +// different programming environments, including REST APIs and RPC APIs. It is +// used by [gRPC](https://github.com/grpc). Each `Status` message contains +// three pieces of data: error code, error message, and error details. +// +// You can find out more about this error model and how to work with it in the +// [API Design Guide](https://cloud.google.com/apis/design/errors). +message Status { + // The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code]. + int32 code = 1; + + // A developer-facing error message, which should be in English. Any + // user-facing error message should be localized and sent in the + // [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client. + string message = 2; + + // A list of messages that carry the error details. There is a common set of + // message types for APIs to use. + repeated google.protobuf.Any details = 3; +} \ No newline at end of file diff --git a/proto/grpc/health/v1/health.proto b/proto/grpc/health/v1/health.proto new file mode 100644 index 0000000..78dde9d --- /dev/null +++ b/proto/grpc/health/v1/health.proto @@ -0,0 +1,63 @@ +// Copyright 2015 The gRPC Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// The canonical version of this proto can be found at +// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto + +syntax = "proto3"; + +package grpc.health.v1; + +option csharp_namespace = "Grpc.Health.V1"; +option go_package = "google.golang.org/grpc/health/grpc_health_v1"; +option java_multiple_files = true; +option java_outer_classname = "HealthProto"; +option java_package = "io.grpc.health.v1"; + +message HealthCheckRequest { + string service = 1; +} + +message HealthCheckResponse { + enum ServingStatus { + UNKNOWN = 0; + SERVING = 1; + NOT_SERVING = 2; + SERVICE_UNKNOWN = 3; // Used only by the Watch method. + } + ServingStatus status = 1; +} + +service Health { + // If the requested service is unknown, the call will fail with status + // NOT_FOUND. + rpc Check(HealthCheckRequest) returns (HealthCheckResponse); + + // Performs a watch for the serving status of the requested service. + // The server will immediately send back a message indicating the current + // serving status. It will then subsequently send a new message whenever + // the service's serving status changes. + // + // If the requested service is unknown when the call is received, the + // server will send a message setting the serving status to + // SERVICE_UNKNOWN but will *not* terminate the call. If at some + // future point, the serving status of the service becomes known, the + // server will send a new message with the service's serving status. + // + // If the call terminates with status UNIMPLEMENTED, then clients + // should assume this method is not supported and should not retry the + // call. If the call terminates with any other status (including OK), + // clients should retry the call with appropriate exponential backoff. + rpc Watch(HealthCheckRequest) returns (stream HealthCheckResponse); +} \ No newline at end of file diff --git a/proto/grpc/reflection/v1alpha/reflection.proto b/proto/grpc/reflection/v1alpha/reflection.proto new file mode 100644 index 0000000..b09b1b6 --- /dev/null +++ b/proto/grpc/reflection/v1alpha/reflection.proto @@ -0,0 +1,136 @@ +// Copyright 2016 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Service exported by server reflection + +syntax = "proto3"; + +package grpc.reflection.v1alpha; + +service ServerReflection { + // The reflection service is structured as a bidirectional stream, ensuring + // all related requests go to a single server. + rpc ServerReflectionInfo(stream ServerReflectionRequest) + returns (stream ServerReflectionResponse); +} + +// The message sent by the client when calling ServerReflectionInfo method. +message ServerReflectionRequest { + string host = 1; + // To use reflection service, the client should set one of the following + // fields in message_request. The server distinguishes requests by their + // defined field and then handles them using corresponding methods. + oneof message_request { + // Find a proto file by the file name. + string file_by_filename = 3; + + // Find the proto file that declares the given fully-qualified symbol name. + // This field should be a fully-qualified symbol name + // (e.g. .[.] or .). + string file_containing_symbol = 4; + + // Find the proto file which defines an extension extending the given + // message type with the given field number. + ExtensionRequest file_containing_extension = 5; + + // Finds the tag numbers used by all known extensions of extendee_type, and + // appends them to ExtensionNumberResponse in an undefined order. + // Its corresponding method is best-effort: it's not guaranteed that the + // reflection service will implement this method, and it's not guaranteed + // that this method will provide all extensions. Returns + // StatusCode::UNIMPLEMENTED if it's not implemented. + // This field should be a fully-qualified type name. The format is + // . + string all_extension_numbers_of_type = 6; + + // List the full names of registered services. The content will not be + // checked. + string list_services = 7; + } +} + +// The type name and extension number sent by the client when requesting +// file_containing_extension. +message ExtensionRequest { + // Fully-qualified type name. The format should be . + string containing_type = 1; + int32 extension_number = 2; +} + +// The message sent by the server to answer ServerReflectionInfo method. +message ServerReflectionResponse { + string valid_host = 1; + ServerReflectionRequest original_request = 2; + // The server sets one of the following fields according to the + // message_request in the request. + oneof message_response { + // This message is used to answer file_by_filename, file_containing_symbol, + // file_containing_extension requests with transitive dependencies. + // As the repeated label is not allowed in oneof fields, we use a + // FileDescriptorResponse message to encapsulate the repeated fields. + // The reflection service is allowed to avoid sending FileDescriptorProtos + // that were previously sent in response to earlier requests in the stream. + FileDescriptorResponse file_descriptor_response = 4; + + // This message is used to answer all_extension_numbers_of_type requests. + ExtensionNumberResponse all_extension_numbers_response = 5; + + // This message is used to answer list_services requests. + ListServiceResponse list_services_response = 6; + + // This message is used when an error occurs. + ErrorResponse error_response = 7; + } +} + +// Serialized FileDescriptorProto messages sent by the server answering +// a file_by_filename, file_containing_symbol, or file_containing_extension +// request. +message FileDescriptorResponse { + // Serialized FileDescriptorProto messages. We avoid taking a dependency on + // descriptor.proto, which uses proto2 only features, by making them opaque + // bytes instead. + repeated bytes file_descriptor_proto = 1; +} + +// A list of extension numbers sent by the server answering +// all_extension_numbers_of_type request. +message ExtensionNumberResponse { + // Full name of the base type, including the package name. The format + // is . + string base_type_name = 1; + repeated int32 extension_number = 2; +} + +// A list of ServiceResponse sent by the server answering list_services request. +message ListServiceResponse { + // The information of each service may be expanded in the future, so we use + // ServiceResponse message to encapsulate it. + repeated ServiceResponse service = 1; +} + +// The information of a single service used by ListServiceResponse to answer +// list_services request. +message ServiceResponse { + // Full name of a registered service, including its package name. The format + // is . + string name = 1; +} + +// The error code and error message sent by the server when an error occurs. +message ErrorResponse { + // This field uses the error codes defined in grpc::StatusCode. + int32 error_code = 1; + string error_message = 2; +} \ No newline at end of file