docs: adr-43 update and nft proto comments (#10615)

## Description

During the NFT working group we found that more clarification is needed. 

I've updated comments in NFT proto and regenerated all proto files. 

---

### Author Checklist

*All items are required. Please add a note to the item if the item is not applicable and
please add links to any relevant follow up issues.*

I have...

- [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [x] added `!` to the type prefix if API or client breaking change
- [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting))
- [x] provided a link to the relevant issue or specification
- [x] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules)
- [x] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing)
- [x] added a changelog entry to `CHANGELOG.md`
- [x] included comments for [documenting Go code](https://blog.golang.org/godoc)
- [x] updated the relevant documentation or specification
- [x] reviewed "Files changed" and left comments if necessary
- [ ] confirmed all CI checks have passed

### Reviewers Checklist

*All items are required. Please add a note if the item is not applicable and please add
your handle next to the items reviewed if you only reviewed selected items.*

I have...

- [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title
- [ ] confirmed `!` in the type prefix if API or client breaking change
- [ ] confirmed all author checklist items have been addressed 
- [ ] reviewed state machine logic
- [ ] reviewed API design and naming
- [ ] reviewed documentation is accurate
- [ ] reviewed tests and test coverage
- [ ] manually tested (if applicable)
This commit is contained in:
Robert Zaremba 2021-11-29 09:53:04 +01:00 committed by GitHub
parent 08a335fd25
commit 32c960a342
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 75 additions and 66 deletions

View File

@ -2,13 +2,12 @@
## Changelog
- 05.05.2021: Initial Draft
- 07.01.2021: Incorporate Billy's feedback
- 07.02.2021: Incorporate feedbacks from Aaron, Shaun, Billy et al.
- 2021-05-01: Initial Draft
- 2021-07-02: Review updates
## Status
DRAFT
PROPOSED
## Abstract
@ -24,7 +23,7 @@ This ADR defines the `x/nft` module which is a generic implementation of NFTs, r
NFTs are more than just crypto art, which is very helpful for accruing value to the Cosmos ecosystem. As a result, Cosmos Hub should implement NFT functions and enable a unified mechanism for storing and sending the ownership representative of NFTs as discussed in https://github.com/cosmos/cosmos-sdk/discussions/9065.
As was discussed in [#9065](https://github.com/cosmos/cosmos-sdk/discussions/9065), several potential solutions can be considered:
As discussed in [#9065](https://github.com/cosmos/cosmos-sdk/discussions/9065), several potential solutions can be considered:
- irismod/nft and modules/incubator/nft
- CW721
@ -34,25 +33,33 @@ As was discussed in [#9065](https://github.com/cosmos/cosmos-sdk/discussions/906
Since functions/use cases of NFTs are tightly connected with their logic, it is almost impossible to support all the NFTs' use cases in one Cosmos SDK module by defining and implementing different transaction types.
Considering generic usage and compatibility of interchain protocols including IBC and Gravity Bridge, it is preferred to have a generic NFT module design which handles the generic NFTs logic.
This design idea can enable composability that application-specific functions should be managed by other modules on Cosmos Hub or on other Zones by importing the NFT module.
The current design is based on the work done by [IRISnet team](https://github.com/irisnet/irismod/tree/master/modules/nft) and an older implementation in the [Cosmos repository](https://github.com/cosmos/modules/tree/master/incubator/nft).
## Decision
We will create a module `x/nft`, which contains the following functionality:
We create a `x/nft` module, which contains the following functionality:
- Store NFTs and track their ownership.
- Expose `Keeper` interface for composing modules to mint and burn NFTs.
- Expose `Keeper` interface for composing modules to transfer, mint and burn NFTs.
- Expose external `Message` interface for users to transfer ownership of their NFTs.
- Query NFTs and their supply information.
The proposed module is a base module for NFT app logic. It's goal it to provide a common layer for storage, basic transfer functionality and IBC. The module should not be used as a standalone.
Instead an app should create a specialized module to handle app specific logic (eg: NFT ID construction, royalty), user level minting and burning. Moreover an app specialized module should handle auxiliary data to support the app logic (eg indexes, ORM, business data).
All data carried over IBC must be part of the `NFT` or `Class` type described below. The app specific NFT data should be encoded in `NFT.data` for cross-chain integrity. Other objects related to NFT, which are not important for integrity can be part of the app specific module.
### Types
We propose two main types:
+ `Class` -- describes NFT class. We can think about it as a smart contract address.
+ `NFT` -- object representing unique, non fungible asset. Each NFT is associated with a Class.
#### Class
We define a model for NFT **Class**, which is comparable to an ERC721 Contract on Ethereum, under which a collection of NFTs can be created and managed.
NFT **Class** is comparable to an ERC-721 smart contract (provides description of a smart contract), under which a collection of NFTs can be created and managed.
```protobuf
message Class {
@ -62,6 +69,7 @@ message Class {
string description = 4;
string uri = 5;
string uri_hash = 6;
google.protobuf.Any data = 7;
}
```
@ -69,8 +77,9 @@ message Class {
- `name` is a descriptive name of the NFT class; _optional_
- `symbol` is the symbol usually shown on exchanges for the NFT class; _optional_
- `description` is a detailed description of the NFT class; _optional_
- `uri` is a URL pointing to an off-chain JSON file that contains metadata about this NFT class ([OpenSea example](https://docs.opensea.io/docs/contract-level-metadata)); _optional_
- `uri_hash` is a hash of the `uri`; _optional_
- `uri` is a URI for the class metadata stored off chain. It should be a JSON file that contains metadata about the NFT class and NFT data schema ([OpenSea example](https://docs.opensea.io/docs/contract-level-metadata)); _optional_
- `uri_hash` is a hash of the document pointed by uri; _optional_
- `data` is app specific metadata of the class; _optional_
#### NFT
@ -93,9 +102,9 @@ message NFT {
{class_id}/{id} --> NFT (bytes)
```
- `uri` is a URL pointing to an off-chain JSON file that contains metadata about this NFT (Ref: [ERC721 standard and OpenSea extension](https://docs.opensea.io/docs/metadata-standards)); _required_
- `uri_hash` is a hash of the `uri`;
- `data` is a field that CAN be used by composing modules to specify additional properties for the NFT; _optional_
- `uri` is a URI for the NFT metadata stored off chain. Should point to a JSON file that contains metadata about this NFT (Ref: [ERC721 standard and OpenSea extension](https://docs.opensea.io/docs/metadata-standards)); _required_
- `uri_hash` is a hash of the document pointed by uri; _optional_
- `data` is an app specific data of the NFT. CAN be used by composing modules to specify additional properties of the NFT; _optional_
This ADR doesn't specify values that `data` can take; however, best practices recommend upper-level NFT modules clearly specify their contents. Although the value of this field doesn't provide the additional context required to manage NFT records, which means that the field can technically be removed from the specification, the field's existence allows basic informational/UI functionality.
@ -319,6 +328,7 @@ This specification conforms to the ERC-721 smart contract specification for NFT
### Negative
+ New IBC app is required for x/nft
+ CW721 adapter is required
### Neutral
@ -330,6 +340,7 @@ For other kinds of applications on the Hub, more app-specific modules can be dev
- `x/nft/custody`: custody of NFTs to support trading functionality.
- `x/nft/marketplace`: selling and buying NFTs using sdk.Coins.
- `x/fractional`: a module to split an ownership of an asset (NFT or other assets) for multiple stakeholder. `x/group` should work for most of the cases.
Other networks in the Cosmos ecosystem could design and implement their own NFT modules for specific NFT applications and use cases.

View File

@ -10,39 +10,39 @@ message Class {
// id defines the unique identifier of the NFT classification, similar to the contract address of ERC721
string id = 1;
// name defines the human-readable name of the NFT classification,optional
// name defines the human-readable name of the NFT classification. Optional
string name = 2;
// symbol is an abbreviated name for nft classification,optional
// symbol is an abbreviated name for nft classification. Optional
string symbol = 3;
// description is a brief description of nft classification,optional
// description is a brief description of nft classification. Optional
string description = 4;
// uri is a URI may point to a JSON file that conforms to the nft classification Metadata JSON Schema.optional
// uri for the class metadata stored off chain. It can define schema for Class and NFT `Data` attributes. Optional
string uri = 5;
// uri_hash is a hash of the document pointed to uri,optional
// uri_hash is a hash of the document pointed by uri. Optional
string uri_hash = 6;
// data is the metadata of NFT classification,optional
// data is the app specific metadata of the NFT class. Optional
google.protobuf.Any data = 7;
}
// NFT defines the NFT.
message NFT {
// class_id defines the unique identifier of the NFT classification, similar to the contract address of ERC721
// class_id associated with the NFT, similar to the contract address of ERC721
string class_id = 1;
// id defines the unique identification of NFT
// id is a unique identifier of the NFT
string id = 2;
// uri defines NFT's metadata storage address outside the chain
// uri for the NFT metadata stored off chain
string uri = 3;
// uri_hash is a hash of the document pointed to uri
// uri_hash is a hash of the document pointed by uri
string uri_hash = 4;
// data is the metadata of the NFT,optional
// data is an app specific data of the NFT. Optional
google.protobuf.Any data = 10;
}
}

View File

@ -5,7 +5,6 @@ package nft
import (
fmt "fmt"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
@ -223,23 +222,22 @@ func init() {
func init() { proto.RegisterFile("cosmos/nft/v1beta1/event.proto", fileDescriptor_49f05440d2b8ed9d) }
var fileDescriptor_49f05440d2b8ed9d = []byte{
// 248 bytes of a gzipped FileDescriptorProto
// 235 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4b, 0xce, 0x2f, 0xce,
0xcd, 0x2f, 0xd6, 0xcf, 0x4b, 0x2b, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x4f,
0x2d, 0x4b, 0xcd, 0x2b, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x82, 0xc8, 0xeb, 0xe5,
0xa5, 0x95, 0xe8, 0x41, 0xe5, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0xd2, 0xfa, 0x20, 0x16,
0x44, 0xa5, 0x52, 0x16, 0x17, 0xa7, 0x2b, 0x48, 0x63, 0x70, 0x6a, 0x5e, 0x8a, 0x90, 0x24, 0x17,
0x47, 0x72, 0x4e, 0x62, 0x71, 0x71, 0x7c, 0x66, 0x8a, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10,
0x3b, 0x98, 0xef, 0x99, 0x22, 0xc4, 0xc7, 0xc5, 0x94, 0x99, 0x22, 0xc1, 0x04, 0x16, 0x64, 0xca,
0x4c, 0x11, 0x12, 0xe3, 0x62, 0x2b, 0x4e, 0xcd, 0x4b, 0x49, 0x2d, 0x92, 0x60, 0x06, 0x8b, 0x41,
0x79, 0x42, 0x52, 0x5c, 0x1c, 0x45, 0xa9, 0xc9, 0xa9, 0x99, 0x65, 0xa9, 0x45, 0x12, 0x2c, 0x60,
0x19, 0x38, 0x5f, 0xc9, 0x07, 0x6a, 0x97, 0x6f, 0x66, 0x5e, 0x09, 0x29, 0x76, 0x89, 0x70, 0xb1,
0xe6, 0x97, 0xe7, 0xc1, 0xad, 0x82, 0x70, 0xe0, 0xa6, 0x39, 0x95, 0x16, 0xe5, 0x51, 0x6c, 0x9a,
0x93, 0xcd, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1,
0xb1, 0x1c, 0xc3, 0x85, 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x29, 0xa5, 0x67, 0x96,
0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x43, 0x83, 0x1d, 0x42, 0xe9, 0x16, 0xa7, 0x64,
0xeb, 0x57, 0x80, 0xe2, 0x20, 0x89, 0x0d, 0x1c, 0x98, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff, 0xff,
0x66, 0x7d, 0x4c, 0x95, 0x98, 0x01, 0x00, 0x00,
0xa5, 0x95, 0xe8, 0x41, 0xe5, 0x95, 0xb2, 0xb8, 0x38, 0x5d, 0x41, 0x4a, 0x82, 0x53, 0xf3, 0x52,
0x84, 0x24, 0xb9, 0x38, 0x92, 0x73, 0x12, 0x8b, 0x8b, 0xe3, 0x33, 0x53, 0x24, 0x18, 0x15, 0x18,
0x35, 0x38, 0x83, 0xd8, 0xc1, 0x7c, 0xcf, 0x14, 0x21, 0x3e, 0x2e, 0xa6, 0xcc, 0x14, 0x09, 0x26,
0xb0, 0x20, 0x53, 0x66, 0x8a, 0x90, 0x18, 0x17, 0x5b, 0x71, 0x6a, 0x5e, 0x4a, 0x6a, 0x91, 0x04,
0x33, 0x58, 0x0c, 0xca, 0x13, 0x92, 0xe2, 0xe2, 0x28, 0x4a, 0x4d, 0x4e, 0xcd, 0x2c, 0x4b, 0x2d,
0x92, 0x60, 0x01, 0xcb, 0xc0, 0xf9, 0x4a, 0x3e, 0x50, 0xbb, 0x7c, 0x33, 0xf3, 0x4a, 0x48, 0xb1,
0x4b, 0x84, 0x8b, 0x35, 0xbf, 0x3c, 0x0f, 0x6e, 0x15, 0x84, 0x03, 0x37, 0xcd, 0xa9, 0xb4, 0x28,
0x8f, 0x62, 0xd3, 0x9c, 0x6c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23,
0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0x4a,
0x29, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0x1a, 0xc0, 0x10, 0x4a,
0xb7, 0x38, 0x25, 0x5b, 0xbf, 0x02, 0x14, 0xda, 0x49, 0x6c, 0xe0, 0x00, 0x36, 0x06, 0x04, 0x00,
0x00, 0xff, 0xff, 0x29, 0x44, 0x2b, 0xe7, 0x82, 0x01, 0x00, 0x00,
}
func (m *EventSend) Marshal() (dAtA []byte, err error) {

View File

@ -27,17 +27,17 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type Class struct {
// id defines the unique identifier of the NFT classification, similar to the contract address of ERC721
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// name defines the human-readable name of the NFT classification,optional
// name defines the human-readable name of the NFT classification. Optional
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
// symbol is an abbreviated name for nft classification,optional
// symbol is an abbreviated name for nft classification. Optional
Symbol string `protobuf:"bytes,3,opt,name=symbol,proto3" json:"symbol,omitempty"`
// description is a brief description of nft classification,optional
// description is a brief description of nft classification. Optional
Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"`
// uri is a URI may point to a JSON file that conforms to the nft classification Metadata JSON Schema.optional
// uri for the class metadata stored off chain. It can define schema for Class and NFT `Data` attributes. Optional
Uri string `protobuf:"bytes,5,opt,name=uri,proto3" json:"uri,omitempty"`
// uri_hash is a hash of the document pointed to uri,optional
// uri_hash is a hash of the document pointed by uri. Optional
UriHash string `protobuf:"bytes,6,opt,name=uri_hash,json=uriHash,proto3" json:"uri_hash,omitempty"`
// data is the metadata of NFT classification,optional
// data is the app specific metadata of the NFT class. Optional
Data *types.Any `protobuf:"bytes,7,opt,name=data,proto3" json:"data,omitempty"`
}
@ -125,15 +125,15 @@ func (m *Class) GetData() *types.Any {
// NFT defines the NFT.
type NFT struct {
// class_id defines the unique identifier of the NFT classification, similar to the contract address of ERC721
// class_id associated with the NFT, similar to the contract address of ERC721
ClassId string `protobuf:"bytes,1,opt,name=class_id,json=classId,proto3" json:"class_id,omitempty"`
// id defines the unique identification of NFT
// id is a unique identifier of the NFT
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
// uri defines NFT's metadata storage address outside the chain
// uri for the NFT metadata stored off chain
Uri string `protobuf:"bytes,3,opt,name=uri,proto3" json:"uri,omitempty"`
// uri_hash is a hash of the document pointed to uri
// uri_hash is a hash of the document pointed by uri
UriHash string `protobuf:"bytes,4,opt,name=uri_hash,json=uriHash,proto3" json:"uri_hash,omitempty"`
// data is the metadata of the NFT,optional
// data is an app specific data of the NFT. Optional
Data *types.Any `protobuf:"bytes,10,opt,name=data,proto3" json:"data,omitempty"`
}

View File

@ -145,23 +145,23 @@ func init() {
func init() { proto.RegisterFile("cosmos/nft/v1beta1/tx.proto", fileDescriptor_35818c6a0ef51f08) }
var fileDescriptor_35818c6a0ef51f08 = []byte{
// 252 bytes of a gzipped FileDescriptorProto
// 244 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4e, 0xce, 0x2f, 0xce,
0xcd, 0x2f, 0xd6, 0xcf, 0x4b, 0x2b, 0xd1, 0x2f, 0x33, 0x4c, 0x4a, 0x2d, 0x49, 0x34, 0xd4, 0x2f,
0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x82, 0x48, 0xea, 0xe5, 0xa5, 0x95, 0xe8,
0x41, 0x25, 0xa5, 0x64, 0xb0, 0x68, 0x00, 0xc9, 0x83, 0x75, 0x28, 0x65, 0x70, 0xb1, 0xfb, 0x16,
0xa7, 0x07, 0xa7, 0xe6, 0xa5, 0x08, 0x49, 0x72, 0x71, 0x24, 0xe7, 0x24, 0x16, 0x17, 0xc7, 0x67,
0xa6, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0xb1, 0x83, 0xf9, 0x9e, 0x29, 0x42, 0x7c, 0x5c,
0x4c, 0x99, 0x29, 0x12, 0x4c, 0x60, 0x41, 0xa6, 0xcc, 0x14, 0x21, 0x31, 0x2e, 0xb6, 0xe2, 0xd4,
0xbc, 0x94, 0xd4, 0x22, 0x09, 0x66, 0xb0, 0x18, 0x94, 0x27, 0x24, 0xc5, 0xc5, 0x51, 0x94, 0x9a,
0x9c, 0x9a, 0x59, 0x96, 0x5a, 0x24, 0xc1, 0x02, 0x96, 0x81, 0xf3, 0x95, 0x04, 0xb9, 0xf8, 0xa1,
0x36, 0x05, 0xa5, 0x16, 0x17, 0xe4, 0xe7, 0x15, 0xa7, 0x1a, 0xf9, 0x73, 0x31, 0xfb, 0x16, 0xa7,
0x0b, 0x79, 0x70, 0xb1, 0x80, 0x1d, 0x20, 0xad, 0x87, 0xe9, 0x7c, 0x3d, 0xa8, 0x1e, 0x29, 0x65,
0x3c, 0x92, 0x30, 0x03, 0x9d, 0x6c, 0x4e, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1,
0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21,
0x4a, 0x29, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x1f, 0x1a, 0x20, 0x10,
0x4a, 0xb7, 0x38, 0x25, 0x5b, 0xbf, 0x02, 0x14, 0x22, 0x49, 0x6c, 0xe0, 0x20, 0x31, 0x06, 0x04,
0x00, 0x00, 0xff, 0xff, 0x63, 0xa3, 0x43, 0x38, 0x63, 0x01, 0x00, 0x00,
0x41, 0x25, 0x95, 0x32, 0xb8, 0xd8, 0x7d, 0x8b, 0xd3, 0x83, 0x53, 0xf3, 0x52, 0x84, 0x24, 0xb9,
0x38, 0x92, 0x73, 0x12, 0x8b, 0x8b, 0xe3, 0x33, 0x53, 0x24, 0x18, 0x15, 0x18, 0x35, 0x38, 0x83,
0xd8, 0xc1, 0x7c, 0xcf, 0x14, 0x21, 0x3e, 0x2e, 0xa6, 0xcc, 0x14, 0x09, 0x26, 0xb0, 0x20, 0x53,
0x66, 0x8a, 0x90, 0x18, 0x17, 0x5b, 0x71, 0x6a, 0x5e, 0x4a, 0x6a, 0x91, 0x04, 0x33, 0x58, 0x0c,
0xca, 0x13, 0x92, 0xe2, 0xe2, 0x28, 0x4a, 0x4d, 0x4e, 0xcd, 0x2c, 0x4b, 0x2d, 0x92, 0x60, 0x01,
0xcb, 0xc0, 0xf9, 0x4a, 0x82, 0x5c, 0xfc, 0x50, 0x9b, 0x82, 0x52, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a,
0x53, 0x8d, 0xfc, 0xb9, 0x98, 0x7d, 0x8b, 0xd3, 0x85, 0x3c, 0xb8, 0x58, 0xc0, 0x0e, 0x90, 0xd6,
0xc3, 0x74, 0xa0, 0x1e, 0x54, 0x8f, 0x94, 0x32, 0x1e, 0x49, 0x98, 0x81, 0x4e, 0x36, 0x27, 0x1e,
0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17,
0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x94, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4,
0x97, 0x9c, 0x9f, 0xab, 0x0f, 0x0d, 0x23, 0x08, 0xa5, 0x5b, 0x9c, 0x92, 0xad, 0x5f, 0x01, 0x0a,
0xb0, 0x24, 0x36, 0x70, 0x30, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x40, 0xdf, 0xd5, 0xe6,
0x45, 0x01, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.