From 7ea9569808aaa25a269c5b4886fcd2a561128d4f Mon Sep 17 00:00:00 2001 From: Dominic Wong Date: Fri, 25 Feb 2022 13:06:19 +0000 Subject: [PATCH] NFT asset and collection endpoints (#389) --- nft/domain/opensea.go | 34 +- nft/examples.json | 698 +++++++++++++++++++++++++++++++++ nft/handler/opensea.go | 360 ++++++++++------- nft/proto/nft.pb.go | 787 +++++++++++++++++++++++++++++--------- nft/proto/nft.pb.micro.go | 35 ++ nft/proto/nft.proto | 47 +++ 6 files changed, 1628 insertions(+), 333 deletions(-) diff --git a/nft/domain/opensea.go b/nft/domain/opensea.go index ef30563..dfe457d 100644 --- a/nft/domain/opensea.go +++ b/nft/domain/opensea.go @@ -1,5 +1,7 @@ package domain +import "encoding/json" + type AssetsResponse struct { Assets []*Asset `json:"assets"` } @@ -8,6 +10,10 @@ type CollectionsResponse struct { Collections []*Collection `json:"collections"` } +type CollectionResponse struct { + Collection *Collection `json:"collection"` +} + type Asset struct { Id int32 `json:"id"` TokenId string `json:"token_id"` @@ -23,6 +29,8 @@ type Asset struct { LastSale *Sale `json:"last_sale,omitempty"` Presale bool `json:"is_presale"` ListingDate string `json:"listing_date,omitempty"` + + Traits []map[string]interface{} `json:"traits,omitempty"` } type Contract struct { @@ -55,6 +63,16 @@ type Collection struct { ImageUrl string `json:"image_url,omitempty"` CreatedAt string `json:"created_date,omitempty"` PayoutAddress string `json:"payout_address,omitempty"` + + ExternalLink string `json:"external_link,omitempty"` + BannerImageUrl string `json:"banner_image_url,omitempty"` + DevSellerFeeBasisPoints string `json:"dev_seller_fee_basis_points,omitempty"` + SafelistRequestStatus string `json:"safelist_request_status,omitempty"` + PrimaryAssetContracts []Contract `json:"primary_asset_contracts,omitempty"` + Traits map[string]interface{} `json:"traits,omitempty"` + PaymentTokens []Token `json:"payment_tokens,omitempty"` + Editors []string `json:"editors,omitempty"` + Stats map[string]interface{} `json:"stats,omitempty"` } type User struct { @@ -95,12 +113,12 @@ type Transaction struct { } type Token struct { - Id int32 `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Symbol string `json:"symbol,omitempty"` - Address string `json:"address,omitempty"` - ImageUrl string `json:"image_url,omitempty"` - Decimals int32 `json:"decimals,omitempty"` - EthPrice string `json:"eth_price,omitempty"` - UsdPrice string `json:"usd_price,omitempty"` + Id int32 `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Symbol string `json:"symbol,omitempty"` + Address string `json:"address,omitempty"` + ImageUrl string `json:"image_url,omitempty"` + Decimals int32 `json:"decimals,omitempty"` + EthPrice json.Number `json:"eth_price,omitempty"` + UsdPrice json.Number `json:"usd_price,omitempty"` } diff --git a/nft/examples.json b/nft/examples.json index 9e36dcc..eba6dd6 100644 --- a/nft/examples.json +++ b/nft/examples.json @@ -122,5 +122,703 @@ ] } } + ], + "asset": [ + { + "title": "Get a single asset", + "run_check": false, + "request": { + "contract_address": "0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb", + "token_id": "1" + }, + "response": + { + "asset": { + "id": 158831, + "token_id": "1", + "name": "CryptoPunk #1", + "description": "", + "image_url": "https://lh3.googleusercontent.com/7bRocEaoBrWYBX3vThkHj4kAV3b3mKG-Kem85xeT-D8oHpvQ19kcoiBd9mIFeNU0GrwZGvj6Oc5NAEGBSsGlrww", + "sales": 3, + "permalink": "https://opensea.io/assets/0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb/1", + "contract": { + "name": "CryptoPunks", + "address": "0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb", + "type": "non-fungible", + "created_at": "2018-01-23T04:51:38.832339", + "owner": 0, + "schema": "CRYPTOPUNKS", + "symbol": "PUNK", + "description": "CryptoPunks launched as a fixed set of 10,000 items in mid-2017 and became one of the inspirations for the ERC-721 standard. They have been featured in places like The New York Times, Christie’s of London, Art|Basel Miami, and The PBS NewsHour.", + "payout_address": "", + "seller_fees": "" + }, + "collection": { + "name": "CryptoPunks", + "description": "CryptoPunks launched as a fixed set of 10,000 items in mid-2017 and became one of the inspirations for the ERC-721 standard. They have been featured in places like The New York Times, Christie’s of London, Art|Basel Miami, and The PBS NewsHour.", + "slug": "cryptopunks", + "image_url": "https://lh3.googleusercontent.com/BdxvLseXcfl57BiuQcQYdJ64v-aI8din7WPk0Pgo3qQFhAUH-B6i-dCqqc_mCkRIzULmwzwecnohLhrcH8A9mpWIZqA7ygc52Sr81hE=s120", + "created_at": "2019-04-26T22:13:09.691572", + "payout_address": "", + "external_link": "", + "banner_image_url": "https://lh3.googleusercontent.com/48oVuDyfe_xhs24BC2TTVcaYCX7rrU5mpuQLyTgRDbKHj2PtzKZsQ5qC3xTH4ar34wwAXxEKH8uUDPAGffbg7boeGYqX6op5vBDcbA=s2500", + "seller_fees": "0", + "safelist_request_status": "verified", + "primary_asset_contracts": [ + { + "name": "CryptoPunks", + "address": "0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb", + "type": "non-fungible", + "created_at": "2018-01-23T04:51:38.832339", + "owner": 0, + "schema": "CRYPTOPUNKS", + "symbol": "PUNK", + "description": "CryptoPunks launched as a fixed set of 10,000 items in mid-2017 and became one of the inspirations for the ERC-721 standard. They have been featured in places like The New York Times, Christie’s of London, Art|Basel Miami, and The PBS NewsHour.", + "payout_address": "", + "seller_fees": "" + } + ], + "traits": {}, + "payment_tokens": [ + { + "id": 4403908, + "name": "USD Coin", + "symbol": "USDC", + "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", + "image_url": "https://storage.opensea.io/files/749015f009a66abcb3bbb3502ae2f1ce.svg", + "decimals": 6, + "eth_price": "0.00038247", + "usd_price": "1.004" + }, + { + "id": 4645681, + "name": "Wrapped Ether", + "symbol": "WETH", + "address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + "image_url": "https://storage.opensea.io/files/accae6b6fb3888cbff27a013729c22dc.svg", + "decimals": 18, + "eth_price": "1.0", + "usd_price": "2618.9" + }, + { + "id": 13689077, + "name": "Ether", + "symbol": "ETH", + "address": "0x0000000000000000000000000000000000000000", + "image_url": "https://storage.opensea.io/files/6f8e2979d428180222796ff4a33ab929.svg", + "decimals": 18, + "eth_price": "1.0", + "usd_price": "2618.9" + }, + { + "id": 12182941, + "name": "Dai Stablecoin", + "symbol": "DAI", + "address": "0x6b175474e89094c44da98b954eedeac495271d0f", + "image_url": "https://storage.opensea.io/files/8ef8fb3fe707f693e57cdbfea130c24c.svg", + "decimals": 18, + "eth_price": "0.00038184", + "usd_price": "1.002" + } + ], + "editors": [], + "stats": { + "average_price": 44.04037840006798, + "count": 9999, + "floor_price": 0, + "market_cap": 686700.4139999999, + "num_owners": 3410, + "num_reports": 23, + "one_day_average_price": 72.06428571428573, + "one_day_change": 1.0516522623284192, + "one_day_sales": 14, + "one_day_volume": 1008.9000000000002, + "seven_day_average_price": 68.67690909090908, + "seven_day_change": -0.7078843982491145, + "seven_day_sales": 55, + "seven_day_volume": 3777.2299999999996, + "thirty_day_average_price": 112.94592875318067, + "thirty_day_change": 0.22073918742765927, + "thirty_day_sales": 393, + "thirty_day_volume": 44387.75, + "total_sales": 19220, + "total_supply": 9999, + "total_volume": 846456.0728493065 + } + }, + "creator": { + "username": "", + "profile_url": "https://storage.googleapis.com/opensea-static/opensea-profile/22.png", + "address": "0xc352b534e8b987e036a93539fd6897f53488e56a" + }, + "owner": { + "username": "", + "profile_url": "https://storage.googleapis.com/opensea-static/opensea-profile/32.png", + "address": "0xb88f61e6fbda83fbfffabe364112137480398018" + }, + "presale": false, + "last_sale": { + "asset_token_id": "1", + "asset_decimals": 0, + "event_type": "successful", + "event_timestamp": "2020-11-30T18:44:26", + "total_price": "60000000000000000000", + "quantity": "1", + "created_at": "2020-11-30T18:45:11.476313", + "transaction": { + "id": 63641091, + "timestamp": "2020-11-30T18:44:26", + "block_hash": "0xe3eacbc6f4d6bb43525b69baffe09477f452f0f5e1a5b1d5232dc23b6cb176cb", + "block_number": "11361817", + "from_account": { + "username": "GoWestBTC", + "profile_url": "https://storage.googleapis.com/opensea-static/opensea-profile/4.png", + "address": "0xee3766e4f996dc0e0f8c929954eaafef3441de87" + }, + "to_account": { + "username": "", + "profile_url": "https://storage.googleapis.com/opensea-static/opensea-profile/23.png", + "address": "0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb" + }, + "transaction_hash": "0xf4af5563f3c4c3b26dee3ab027902f113bee5985b28d9ede5b81ab42b46abb30", + "transaction_index": "58" + }, + "payment_token": { + "id": 1, + "name": "Ether", + "symbol": "ETH", + "address": "0x0000000000000000000000000000000000000000", + "image_url": "https://storage.opensea.io/files/6f8e2979d428180222796ff4a33ab929.svg", + "decimals": 18, + "eth_price": "1.000000000000000", + "usd_price": "2624.030000000000200000" + } + }, + "listing_date": "", + "traits": [ + { + "display_type": null, + "max_value": null, + "order": null, + "trait_count": 6039, + "trait_type": "type", + "value": "Male" + }, + { + "display_type": null, + "max_value": null, + "order": null, + "trait_count": 441, + "trait_type": "accessory", + "value": "Mohawk" + }, + { + "display_type": null, + "max_value": null, + "order": null, + "trait_count": 238, + "trait_type": "accessory", + "value": "Smile" + }, + { + "display_type": null, + "max_value": null, + "order": null, + "trait_count": 1909, + "trait_type": "accessory", + "value": "2 attributes" + } + ] + } + } + } + ], + "collection": [ + { + "title": "Get a single collection", + "run_check": false, + "request": { + "slug": "doodles-official" + }, + "response": + { + "collection": { + "name": "Doodles", + "description": "A community-driven collectibles project featuring art by Burnt Toast. Doodles come in a joyful range of colors, traits and sizes with a collection size of 10,000. Each Doodle allows its owner to vote for experiences and activations paid for by the Doodles Community Treasury.", + "slug": "doodles-official", + "image_url": "https://lh3.googleusercontent.com/7B0qai02OdHA8P_EOVK672qUliyjQdQDGNrACxs7WnTgZAkJa_wWURnIFKeOh5VTf8cfTqW3wQpozGedaC9mteKphEOtztls02RlWQ=s120", + "created_at": "2021-10-17T13:00:47.419945", + "payout_address": "0xdcd382be6cc4f1971c667ffda85c7a287605afe4", + "external_link": "", + "banner_image_url": "https://lh3.googleusercontent.com/svc_rQkHVGf3aMI14v3pN-ZTI7uDRwN-QayvixX-nHSMZBgb1L1LReSg1-rXj4gNLJgAB0-yD8ERoT-Q2Gu4cy5AuSg-RdHF9bOxFDw=s2500", + "seller_fees": "500", + "safelist_request_status": "verified", + "primary_asset_contracts": [ + { + "name": "Doodles", + "address": "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e", + "type": "non-fungible", + "created_at": "2021-10-16T16:25:03.736944", + "owner": 96236530, + "schema": "ERC721", + "symbol": "DOODLE", + "description": "A community-driven collectibles project featuring art by Burnt Toast. Doodles come in a joyful range of colors, traits and sizes with a collection size of 10,000. Each Doodle allows its owner to vote for experiences and activations paid for by the Doodles Community Treasury.", + "payout_address": "0xdcd382be6cc4f1971c667ffda85c7a287605afe4", + "seller_fees": "" + } + ], + "traits": { + "background": { + "blue": 726, + "blue space": 1, + "bubblegum": 1, + "dark grey": 1, + "dark purple": 2, + "deep space": 1, + "deeper space": 1, + "fire": 313, + "gold": 3, + "gold space": 1, + "gradient 1": 659, + "gradient 2": 664, + "gradient 3": 653, + "gradient 4": 691, + "gradient space": 1, + "green": 749, + "green space": 1, + "grey": 742, + "grey space": 1, + "holographic": 341, + "holographic space": 1, + "iridescent": 436, + "light blue": 703, + "orange": 739, + "pink": 690, + "pink space": 1, + "purple": 692, + "reverse gradient 1": 1, + "sky": 243, + "space": 237, + "starry blue": 1, + "starry purple": 1, + "yellow": 703 + }, + "body": { + "alien": 8, + "blue and yellow jacket": 281, + "blue backpack": 298, + "blue blazer": 104, + "blue fleece": 301, + "blue turtleneck": 313, + "brittle bones skelly": 1, + "bubblegum sweater": 1, + "cat": 9, + "combo 1 puffer": 331, + "combo 2 puffer": 300, + "combo 3 puffer": 300, + "devil cat": 1, + "gold alien": 1, + "gold ape": 1, + "gold bone skelly": 1, + "gold chain": 1, + "gold sweater": 1, + "green blazer": 119, + "green cat": 1, + "green hoodie": 305, + "grey hoodie": 310, + "holographic alien": 1, + "holographic bone skelly": 1, + "holographic cat": 1, + "holographic hoodie": 2, + "holographic sweater": 40, + "leopard hoodie": 67, + "light blue puffer": 308, + "navy sweater": 326, + "orange collar": 323, + "orange puffer": 322, + "pink and green jacket": 298, + "pink and white jacket": 337, + "pink backpack": 333, + "pink fleece": 317, + "pink hoodie": 293, + "pink puffer": 313, + "pink sweater with satchel": 323, + "purple backpack": 1, + "purple chain": 112, + "purple sweater with satchel": 307, + "rainbow striped sweater": 55, + "skelly": 8, + "spotted hoodie": 54, + "spotted sweater": 51, + "stellar sweater": 1, + "striped sweater": 298, + "white collar": 289, + "white puffer": 331, + "white sweater": 354, + "white turtleneck": 327, + "yellow backpack": 316, + "yellow puffer": 346, + "yellow turtleneck": 354 + }, + "face": { + "3d glasses": 203, + "3d glasses with cig": 1, + "60s glasses": 22, + "alien": 8, + "ape": 15, + "aviators with cig": 201, + "aviators with mustache": 153, + "bandana": 378, + "blue beard": 157, + "blue check": 123, + "bubblegum": 1, + "cat": 7, + "cat note": 1, + "catnip": 1, + "chill cig": 557, + "cobain glasses": 389, + "content": 646, + "default": 709, + "designer glasses": 662, + "devil cat": 1, + "dino": 8, + "duck": 11, + "gold alien": 1, + "gold ape": 1, + "green beard": 174, + "grumpy": 685, + "happy": 744, + "happy note": 164, + "holographic": 1, + "holographic alien": 1, + "holographic ape": 1, + "holographic beard": 129, + "holographic cat": 1, + "holographic dino": 3, + "holographic visor": 6, + "in love": 647, + "mad": 6, + "mad note": 121, + "mustache": 455, + "neutral note": 172, + "pink beard": 137, + "pirate skelly": 1, + "puffer up": 22, + "puffer up visor": 5, + "rainbow puke": 118, + "sad note": 170, + "satisfied ape": 1, + "shark": 12, + "skeleton": 166, + "skelly": 1, + "skelly cig": 11, + "stellar": 1, + "straw": 411, + "sunglasses": 694, + "surprised": 680, + "whale": 4 + }, + "hair": { + "ape": 10, + "bed head": 1, + "beige bucket cap": 200, + "blue afro": 271, + "blue alfalfa": 283, + "blue alien": 1, + "blue ape": 1, + "blue brushcut": 325, + "blue bucket cap": 1, + "blue messy": 250, + "blue mohawk": 296, + "blue nerd": 275, + "blue puffballs": 263, + "blue toque": 170, + "brown brushcut": 267, + "brown mullet": 282, + "bubblegum bed head": 1, + "cat": 5, + "cowboy": 172, + "crown": 44, + "crown with holographic long": 17, + "devil cat": 1, + "gold alien": 1, + "gold bed head": 1, + "green alien": 2, + "green ape": 2, + "green bowlcut": 302, + "green brushcut": 264, + "green cat": 1, + "green mullet": 300, + "green puffballs": 302, + "grey alien": 1, + "halo": 176, + "harley": 109, + "helmet": 104, + "holographic afro": 90, + "holographic alien": 2, + "holographic ape": 1, + "holographic bed head": 1, + "holographic bob": 39, + "holographic brushcut": 65, + "holographic cat": 1, + "holographic crown": 33, + "holographic mohawk": 85, + "holographic poopie": 35, + "iridescent alien": 1, + "pink": 250, + "pink alien": 1, + "pink ape": 2, + "pink bucket cap": 212, + "pink headband": 263, + "pink long": 279, + "pink tidy": 256, + "pink toque": 200, + "poopie": 61, + "private skelly": 1, + "purple alfalfa": 271, + "purple alien": 1, + "purple brushcut": 265, + "purple cap": 279, + "purple long": 280, + "purple puffballs": 284, + "rainbow mohawk": 2, + "sailor": 34, + "shaved": 306, + "stellar bed head": 1, + "viking": 114, + "white bucket cap": 207, + "wizard": 74, + "yellow backwards cap": 186, + "yellow bowlcut": 303, + "yellow headband": 293, + "yellow toque": 187 + }, + "head": { + "ape": 12, + "balloon": 31, + "blue": 1042, + "blue alien": 1, + "blue ape": 1, + "brittle bones skelly": 1, + "bubblegum": 1, + "calico cat": 1, + "cat": 8, + "coffee": 32, + "devil": 43, + "devil cat": 1, + "flower": 34, + "gold": 1, + "gold alien": 1, + "gold ape": 1, + "gradient 1": 458, + "gradient 2": 493, + "green": 983, + "green alien": 2, + "green ape": 3, + "green cat": 1, + "grey alien": 1, + "holographic": 1, + "holographic alien": 2, + "holographic ape": 1, + "holographic cat": 1, + "icecream": 17, + "iridescent alien": 1, + "lit": 30, + "med": 952, + "orange": 961, + "pale": 936, + "pickle": 35, + "pink": 970, + "pink alien": 1, + "pink ape": 2, + "popsicle": 21, + "purple": 934, + "purple alien": 1, + "rainbow": 26, + "skelly": 14, + "stellar": 1, + "tan": 997, + "yellow": 944 + }, + "piercing": { + "airpod": 515, + "hoop": 1045, + "pearl": 1078 + } + }, + "payment_tokens": [ + { + "id": 4645681, + "name": "Wrapped Ether", + "symbol": "WETH", + "address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + "image_url": "https://storage.opensea.io/files/accae6b6fb3888cbff27a013729c22dc.svg", + "decimals": 18, + "eth_price": "1.0", + "usd_price": "2618.9" + }, + { + "id": 13689077, + "name": "Ether", + "symbol": "ETH", + "address": "0x0000000000000000000000000000000000000000", + "image_url": "https://storage.opensea.io/files/6f8e2979d428180222796ff4a33ab929.svg", + "decimals": 18, + "eth_price": "1.0", + "usd_price": "2618.9" + } + ], + "editors": [ + "0x0239769a1adf4def9f07da824b80b9c4fcb59593", + "0xe96a1b303a1eb8d04fb973eb2b291b8d591c8f72", + "0x25c24760ff9262d0b62ebbe95a4ff2b302f84d6f", + "0x3453a9b5d6f6d83e691951e88d87f685a73e9687", + "0x792b8795afc44b620f9f93ea42115ae7c773edb4", + "0xffb36e12031d07b4fe71c21cd7a01e29089d86d4", + "0x76107bff7d4bcd85548a2889ec9f94815b7937f7", + "0x2b3ab8e7bb14988616359b78709538b10900ab7d", + "0x0d5ac483e9c5da77dda287b9321bb6e227775f41", + "0x931d24f3dede331bfd02a1aa855e9cbf7f0ea2e7", + "0x4ac2d3391d39e5af436f17594ac7d00d992bef9e", + "0x51e88fbf069a576cc7b2f4438794a184459634bd", + "0xc2740ea77fa9d3cc47c4cda7825a6be96b3c192d", + "0x7c1fd4d5acc15b46729c5fb9279b49cf71178654", + "0x4ff00e6cf23158ccc9e7a6b9a504cd37e5bc0a93", + "0xdf86ed6717d4ad0f3b6a9d80a7d30fa95860c6de", + "0xe7e4ae2f7087358f278b705038d14a4ae296bf9e", + "0x10e328cf4245501cde8b3825d34b605c5f6a436b", + "0xa84618338ee02ec398f6b841c7a888f28f9ae9d6", + "0xd2dfa218b2b30f8b7ce5ccb3142b8429c9d33e7d", + "0xa972551724754e05bed000e2bda663cecd3b6b80", + "0x5a3f8913c9eaca9ac1afae60263f555f97586e43", + "0xf8624fab50ade6831abc6b3162e9d405792dcfd1", + "0x1d131f70dfae405dcdd8538f2eaae514d4710613", + "0xca04d584fc1395acf7405d9323d57abcb1a38afc", + "0x9bf565b6801d795f20a855d88ae4dabea473fa7a", + "0xa5964a40b6b1dbb48b1613af3efbb947310d06ff", + "0x958e1e0be167e89eb05eb81e5ac57d260eb9ba03", + "0xb8c1fece2c2928b1e985f59e8546c2f0c13296d4", + "0x53353e9867e34a48ff5d586dd5f07bc1da3fdf75", + "0xb1109aad77b16d7af2b4e710b83d958927293cce", + "0x444c0173731f487b8e648d7b7671bebc7b7f159c", + "0x7c0cc383b247275eeea044f8be09f20fdc98d8b4", + "0x9e0f9d58497242e09354279886e05b24b1585738", + "0x2580e799f91b96b54370b493852e4475badd3449", + "0xdcb69a45a95cc581a349c7a1e930dd9b96445205", + "0x28679a1a632125fbbf7a68d850e50623194a709e", + "0x12dfab0be61c739d5fd3358e40108bc1a32d579c", + "0x685bd636fb6d4243c4751a4c5d220e55ed6ff21c", + "0x2efecef913149064a497491a288869a3289555eb", + "0xd146ac8ddc2520dcc60674722e776728958f9c91", + "0x5e98629b10d2537988ff63ebb57df7378e08e373", + "0x836fd05a18dc13aa8885a718278e6a316ecca1ff", + "0xd144054f09d17175d66aaa9ee73d7931c627fa9a", + "0xa9e12ae31e972a70e0a10ee47714f06d74cdf9c7", + "0xba207a26d53f673cf71cbd2e71d3d5153210c3e4", + "0xf7e886215cd82e9cacf1b1d2cd7ca5cc01d6488e", + "0xf05633fae0f200064b12b2dfa9b17fbccd91fd81", + "0x825487cdf59fc883c92590981864fc07bab84cf2", + "0xccc948a78350723382ec6369bbe7b2a373b872b3", + "0xb9720be63ea8896956a06d2ded491de125fd705e", + "0xf8f166ca8b0c484b17cf5dc8113736d821e2cf15", + "0x841b57a4e2590d6affb167686f343cb97675a426", + "0x222d9881e2f7e8f8f54ae76594f79e73e9779c41", + "0x0bde34d7a38c7414db64dafba0fe492f60083188", + "0xe948d683cc5e94498f84396f1f80de842d18acaf", + "0x7c3e32b9da9a5ab46c8f715d4ab51e1a74a197ed", + "0x38b292c120cf2cee09bca02a9b21035fe62a98e8", + "0xf2a469a4150925ff9f82c3728dd6d02dbe55371c", + "0x7bd13f8c9bc23d7caff3cb5248c8ba63226df8a1", + "0x0ac374554e8075ac2cccc2b4307adefd827e0137", + "0xce89b8a4db53246456d6794b63ff4b0995f5f25e", + "0xa323f50b3c465742e561feea92cf115c6e4ecf97", + "0xb8ef554b53968a29fd6b83e70b08e75ea32001ce", + "0xd7383c3c94a1e2f1224ec54b06db9fae5352d375", + "0x4dd3eb966dee807893d9e4ff8ac99752eb8a6ab0", + "0xeaf54391793cc80de696d72713d7518c6190bfe0", + "0x333601a803cac32b7d17a38d32c9728a93b422f4", + "0x92b381515bd4851faf3d33a161f7967fd87b1227", + "0x700fe545742485732575a7245f558978adcc1ec4", + "0x82f4f1f00ebffa2dda53ae633e720e5ac62e1c88", + "0x50088f08381e2a04c6c485dab0eb03561a011c41", + "0x4884eb76842f734e0de54d79ad45266072eb68e2", + "0xe744b776234a45cd19d93c170a6c5153235a0f45", + "0x889d43a6f9c2e48b913559a1333ead19e6444499", + "0xd5060323782aebb0cda9c0f4fbf70dd443e2e426", + "0x0aff57bf099a72ee482051d7ebc9786c38e1bf93", + "0xa54fa9de78ca2f27ae50eeca6db17684d5384908", + "0xfdb16a768c4d41d7c0e1e5f5ce1d3c8234f6db0a", + "0xa76ed27cdaa1d1f964111bf56dd4a7d4b7c5f7ed", + "0x5fe3ec09d5b3c7566afab16fb9c4e2c3d2ff0622", + "0xa4a1a4fc58bf49da4e83d8cf8861570901a17679", + "0xf20e95059a3bdbda71f091cfa88424c7636ecaa1", + "0xe6518b10420d5f657b8eb637e2c622cab4be6e66", + "0x710ea68f78103398c5c998ba69d63d26435d7421", + "0xf40ec41d6ca845e6f3abcba98878217b8f551d63", + "0x095b5d221ed6ebcdda14e479ba2e6e8933cb66fd", + "0x10ee35231ff8f7ab5489cfb29648387b5e64a87b", + "0x54fd7a70976c0477b422d3b444fef2601ce60f57", + "0xf982cee77b0b78eb6b6e1f7565c465de99f1d2ee", + "0xa1c557f49786b6100c1a3f4240f3bdbd1b88771f", + "0x56760c83c2ffe4576d8d389fd70d4622bff64025", + "0x7817615d7a814b0c13c1dcda5de218f164860135", + "0x36791c410e271d381b0957dac16c667d3c467a83", + "0xbf5b1431ab4a1c58298040e711b81f37f179c42a", + "0x54498b8af97672b544f759297de9139ce5f5312c", + "0x8212ba86992806d099d2bfef158a03f82f9411d7", + "0x97c4d1090416e9e0661a9d7688b3932cbf323c5f", + "0x3ed0ad7f35eb40e6ea939404b1cfbe5254e217f6", + "0xd0b00382c7ee6d6f8a7ef1fda07750c1d5fa68cb", + "0x719d48fe4cc1984ad5992b9eab9f5c962d9c81a8", + "0x84bee312e24de23581388f85fd3a09b9f18b5093", + "0xc8fe620d5a7b5591bc0cb083d84e296937a1f63e", + "0xeeadc5701b5fd25fbcc7fbf04b048cdb1fff1c65", + "0x347b87ea54d4f99b5fc5f61e4822e6bff2efb010", + "0x2a12abad1deec70b27cbfea70fc40e6199b99ae6", + "0x3e275ddf0b02dc4626deba238d175295064c0efe", + "0xd1f93089d9004004f8e30c54de5a584902962ce8", + "0x530cf036ed4fa58f7301a9c788c9806624cefd19", + "0x53969c1464763c7af8a9b9759c5253bf453490dc", + "0x066932897c2375eb307cf05f3104d61fd8299130", + "0xd9d52f157f4ea47f52639e8bf606775d18bea317", + "0xd43809d61e5f42debc180e71c3c1acf3f621a312", + "0x4f0124d010a29a81855ab72c59447b6186153250", + "0x0359c0b2b30ff5e52893156c1baba2b55a468700", + "0x04a190d66f638bd6f1c997c00a91c5b3a523d4a3", + "0x8eaf5461e19fced3c47e024cbff5b3bb55adbb0e", + "0x75479b52c8ccbd74716fb3ea17074aaef14c66a2", + "0x5370eb1675b9ce1d6492f59b4376e4bf67105bb8", + "0x175c1319fe37d8b28a208daac7b41a6e413c1c75", + "0xa7d40978d31785eb5805503accb3249f1c922a52", + "0x94c7c5f905fc888ddc48c51a90b68ddec44f8d8c", + "0x6fb94110aad7d1dbe711fc80febb552bb9f52a25", + "0x9f6ac750a020d3141838cbf35b444fd5b732ec7d" + ], + "stats": { + "average_price": 4.299020396948045, + "count": 10000, + "floor_price": 12.79, + "market_cap": 127608.96407487048, + "num_owners": 6087, + "num_reports": 8, + "one_day_average_price": 12.374149315068497, + "one_day_change": 0.11782178217821812, + "one_day_sales": 73, + "one_day_volume": 903.3129000000002, + "seven_day_average_price": 12.76089640748705, + "seven_day_change": 0.38349631271476725, + "seven_day_sales": 244, + "seven_day_volume": 3113.65872342684, + "thirty_day_average_price": 14.938451873942954, + "thirty_day_change": -0.4939059441234616, + "thirty_day_sales": 1158, + "thirty_day_volume": 17298.727270025942, + "total_sales": 19550, + "total_supply": 10000, + "total_volume": 84045.84876033428 + } + } + } + } ] } diff --git a/nft/handler/opensea.go b/nft/handler/opensea.go index aac0204..27ac29e 100644 --- a/nft/handler/opensea.go +++ b/nft/handler/opensea.go @@ -10,6 +10,7 @@ import ( "github.com/micro/services/nft/domain" pb "github.com/micro/services/nft/proto" "github.com/micro/services/pkg/api" + "google.golang.org/protobuf/types/known/structpb" ) // OpenSea handler @@ -87,140 +88,193 @@ func (o *OpenSea) Assets(ctx context.Context, req *pb.AssetsRequest, rsp *pb.Ass } for _, asset := range resp.Assets { - if asset.Creator == nil { - asset.Creator = &domain.User{ - User: &domain.Username{}, - } - } - if asset.Creator.User == nil { - asset.Creator.User = &domain.Username{} - } - if asset.Owner == nil { - asset.Owner = &domain.User{ - User: &domain.Username{}, - } - } - if asset.Owner.User == nil { - asset.Owner.User = &domain.Username{} - } - if asset.Collection == nil { - asset.Collection = new(domain.Collection) - } - if asset.Contract == nil { - asset.Contract = new(domain.Contract) - } - - lastSale := new(pb.Sale) - - if asset.LastSale != nil { - if asset.LastSale.Transaction == nil { - asset.LastSale.Transaction = &domain.Transaction{ - FromAccount: &domain.User{User: new(domain.Username)}, - ToAccount: &domain.User{User: new(domain.Username)}, - } - } - if asset.LastSale.Transaction.FromAccount == nil { - asset.LastSale.Transaction.FromAccount = &domain.User{User: new(domain.Username)} - } - if asset.LastSale.Transaction.FromAccount.User == nil { - asset.LastSale.Transaction.FromAccount.User = new(domain.Username) - } - if asset.LastSale.Transaction.ToAccount == nil { - asset.LastSale.Transaction.ToAccount = &domain.User{User: new(domain.Username)} - } - if asset.LastSale.Transaction.ToAccount.User == nil { - asset.LastSale.Transaction.ToAccount.User = new(domain.Username) - } - if asset.LastSale.PaymentToken == nil { - asset.LastSale.PaymentToken = new(domain.Token) - } - - lastSale = &pb.Sale{ - AssetTokenId: asset.LastSale.Asset.TokenId, - AssetDecimals: asset.LastSale.Asset.Decimals, - EventType: asset.LastSale.EventType, - EventTimestamp: asset.LastSale.EventTimestamp, - TotalPrice: asset.LastSale.TotalPrice, - Quantity: asset.LastSale.Quantity, - CreatedAt: asset.LastSale.CreatedAt, - Transaction: &pb.Transaction{ - Id: asset.LastSale.Transaction.Id, - Timestamp: asset.LastSale.Transaction.Timestamp, - BlockHash: asset.LastSale.Transaction.BlockHash, - BlockNumber: asset.LastSale.Transaction.BlockNumber, - FromAccount: &pb.User{ - Username: asset.LastSale.Transaction.FromAccount.User.Username, - ProfileUrl: asset.LastSale.Transaction.FromAccount.ProfileUrl, - Address: asset.LastSale.Transaction.FromAccount.Address, - }, - ToAccount: &pb.User{ - Username: asset.LastSale.Transaction.ToAccount.User.Username, - ProfileUrl: asset.LastSale.Transaction.ToAccount.ProfileUrl, - Address: asset.LastSale.Transaction.ToAccount.Address, - }, - TransactionHash: asset.LastSale.Transaction.TransactionHash, - TransactionIndex: asset.LastSale.Transaction.TransactionIndex, - }, - PaymentToken: &pb.Token{ - Id: asset.LastSale.PaymentToken.Id, - Name: asset.LastSale.PaymentToken.Name, - Symbol: asset.LastSale.PaymentToken.Symbol, - Address: asset.LastSale.PaymentToken.Address, - ImageUrl: asset.LastSale.PaymentToken.ImageUrl, - Decimals: asset.LastSale.PaymentToken.Decimals, - EthPrice: asset.LastSale.PaymentToken.EthPrice, - UsdPrice: asset.LastSale.PaymentToken.UsdPrice, - }, - } - } - - rsp.Assets = append(rsp.Assets, &pb.Asset{ - Name: asset.Name, - Description: asset.Description, - Id: asset.Id, - TokenId: asset.TokenId, - ImageUrl: asset.ImageUrl, - Sales: asset.Sales, - Permalink: asset.Permalink, - Contract: &pb.Contract{ - Name: asset.Contract.Name, - Description: asset.Contract.Description, - Address: asset.Contract.Address, - Type: asset.Contract.Type, - CreatedAt: asset.Contract.CreatedAt, - Owner: asset.Contract.Owner, - Schema: asset.Contract.Schema, - Symbol: asset.Contract.Symbol, - PayoutAddress: asset.Contract.PayoutAddress, - SellerFees: asset.Contract.SellerFees, - }, - Collection: &pb.Collection{ - Name: asset.Collection.Name, - Description: asset.Collection.Description, - Slug: asset.Collection.Slug, - ImageUrl: asset.Collection.ImageUrl, - CreatedAt: asset.Collection.CreatedAt, - PayoutAddress: asset.Collection.PayoutAddress, - }, - Owner: &pb.User{ - Username: asset.Owner.User.Username, - ProfileUrl: asset.Owner.ProfileUrl, - Address: asset.Owner.Address, - }, - Creator: &pb.User{ - Username: asset.Creator.User.Username, - ProfileUrl: asset.Creator.ProfileUrl, - Address: asset.Creator.Address, - }, - LastSale: lastSale, - Presale: asset.Presale, - ListingDate: asset.ListingDate, - }) + rsp.Assets = append(rsp.Assets, assetToPb(asset)) } return nil } +func paymentTokenToPb(token *domain.Token) *pb.Token { + if token == nil { + return &pb.Token{} + } + return &pb.Token{ + Id: token.Id, + Name: token.Name, + Symbol: token.Symbol, + Address: token.Address, + ImageUrl: token.ImageUrl, + Decimals: token.Decimals, + // converting to string for backwards compat + EthPrice: fmt.Sprintf("%v", token.EthPrice), + UsdPrice: fmt.Sprintf("%v", token.UsdPrice), + } +} + +func contractToPb(contract *domain.Contract) *pb.Contract { + if contract == nil { + return &pb.Contract{} + } + return &pb.Contract{ + Name: contract.Name, + Description: contract.Description, + Address: contract.Address, + Type: contract.Type, + CreatedAt: contract.CreatedAt, + Owner: contract.Owner, + Schema: contract.Schema, + Symbol: contract.Symbol, + PayoutAddress: contract.PayoutAddress, + SellerFees: contract.SellerFees, + } +} + +func collectionToPb(collection *domain.Collection) *pb.Collection { + if collection == nil { + return &pb.Collection{} + } + ret := &pb.Collection{ + Name: collection.Name, + Description: collection.Description, + Slug: collection.Slug, + ImageUrl: collection.ImageUrl, + CreatedAt: collection.CreatedAt, + PayoutAddress: collection.PayoutAddress, + ExternalLink: collection.ExternalLink, + BannerImageUrl: collection.BannerImageUrl, + SellerFees: collection.DevSellerFeeBasisPoints, + SafelistRequestStatus: collection.SafelistRequestStatus, + PrimaryAssetContracts: func() []*pb.Contract { + cons := make([]*pb.Contract, len(collection.PrimaryAssetContracts)) + for i, c := range collection.PrimaryAssetContracts { + cons[i] = contractToPb(&c) + } + return cons + }(), + PaymentTokens: func() []*pb.Token { + toks := make([]*pb.Token, len(collection.PaymentTokens)) + for i, t := range collection.PaymentTokens { + toks[i] = paymentTokenToPb(&t) + } + return toks + }(), + Editors: collection.Editors, + } + ret.Traits, _ = structpb.NewStruct(collection.Traits) + ret.Stats, _ = structpb.NewStruct(collection.Stats) + return ret +} + +func assetToPb(asset *domain.Asset) *pb.Asset { + if asset.Creator == nil { + asset.Creator = &domain.User{ + User: &domain.Username{}, + } + } + if asset.Creator.User == nil { + asset.Creator.User = &domain.Username{} + } + if asset.Owner == nil { + asset.Owner = &domain.User{ + User: &domain.Username{}, + } + } + if asset.Owner.User == nil { + asset.Owner.User = &domain.Username{} + } + if asset.Collection == nil { + asset.Collection = new(domain.Collection) + } + if asset.Contract == nil { + asset.Contract = new(domain.Contract) + } + + lastSale := new(pb.Sale) + + if asset.LastSale != nil { + if asset.LastSale.Transaction == nil { + asset.LastSale.Transaction = &domain.Transaction{ + FromAccount: &domain.User{User: new(domain.Username)}, + ToAccount: &domain.User{User: new(domain.Username)}, + } + } + if asset.LastSale.Transaction.FromAccount == nil { + asset.LastSale.Transaction.FromAccount = &domain.User{User: new(domain.Username)} + } + if asset.LastSale.Transaction.FromAccount.User == nil { + asset.LastSale.Transaction.FromAccount.User = new(domain.Username) + } + if asset.LastSale.Transaction.ToAccount == nil { + asset.LastSale.Transaction.ToAccount = &domain.User{User: new(domain.Username)} + } + if asset.LastSale.Transaction.ToAccount.User == nil { + asset.LastSale.Transaction.ToAccount.User = new(domain.Username) + } + if asset.LastSale.PaymentToken == nil { + asset.LastSale.PaymentToken = new(domain.Token) + } + + lastSale = &pb.Sale{ + AssetTokenId: asset.LastSale.Asset.TokenId, + AssetDecimals: asset.LastSale.Asset.Decimals, + EventType: asset.LastSale.EventType, + EventTimestamp: asset.LastSale.EventTimestamp, + TotalPrice: asset.LastSale.TotalPrice, + Quantity: asset.LastSale.Quantity, + CreatedAt: asset.LastSale.CreatedAt, + Transaction: &pb.Transaction{ + Id: asset.LastSale.Transaction.Id, + Timestamp: asset.LastSale.Transaction.Timestamp, + BlockHash: asset.LastSale.Transaction.BlockHash, + BlockNumber: asset.LastSale.Transaction.BlockNumber, + FromAccount: &pb.User{ + Username: asset.LastSale.Transaction.FromAccount.User.Username, + ProfileUrl: asset.LastSale.Transaction.FromAccount.ProfileUrl, + Address: asset.LastSale.Transaction.FromAccount.Address, + }, + ToAccount: &pb.User{ + Username: asset.LastSale.Transaction.ToAccount.User.Username, + ProfileUrl: asset.LastSale.Transaction.ToAccount.ProfileUrl, + Address: asset.LastSale.Transaction.ToAccount.Address, + }, + TransactionHash: asset.LastSale.Transaction.TransactionHash, + TransactionIndex: asset.LastSale.Transaction.TransactionIndex, + }, + PaymentToken: paymentTokenToPb(asset.LastSale.PaymentToken), + } + } + traits := make([]*structpb.Struct, len(asset.Traits)) + for i, t := range asset.Traits { + traits[i], _ = structpb.NewStruct(t) + } + + return &pb.Asset{ + Name: asset.Name, + Description: asset.Description, + Id: asset.Id, + TokenId: asset.TokenId, + ImageUrl: asset.ImageUrl, + Sales: asset.Sales, + Permalink: asset.Permalink, + Contract: contractToPb(asset.Contract), + Collection: collectionToPb(asset.Collection), + Owner: &pb.User{ + Username: asset.Owner.User.Username, + ProfileUrl: asset.Owner.ProfileUrl, + Address: asset.Owner.Address, + }, + Creator: &pb.User{ + Username: asset.Creator.User.Username, + ProfileUrl: asset.Creator.ProfileUrl, + Address: asset.Creator.Address, + }, + LastSale: lastSale, + Presale: asset.Presale, + ListingDate: asset.ListingDate, + Traits: traits, + } +} + func (o *OpenSea) Create(ctx context.Context, req *pb.CreateRequest, rsp *pb.CreateResponse) error { return errors.BadRequest("nft.create", "coming soon") } @@ -249,15 +303,47 @@ func (o *OpenSea) Collections(ctx context.Context, req *pb.CollectionsRequest, r } for _, collection := range resp.Collections { - rsp.Collections = append(rsp.Collections, &pb.Collection{ - Name: collection.Name, - Description: collection.Description, - Slug: collection.Slug, - ImageUrl: collection.ImageUrl, - CreatedAt: collection.CreatedAt, - PayoutAddress: collection.PayoutAddress, - }) + rsp.Collections = append(rsp.Collections, collectionToPb(collection)) } return nil } + +func (o *OpenSea) Asset(ctx context.Context, req *pb.AssetRequest, rsp *pb.AssetResponse) error { + if len(req.ContractAddress) == 0 { + return errors.BadRequest("nft.asset", "Missing contract address param") + } + if len(req.TokenId) == 0 { + return errors.BadRequest("nft.asset", "Missing token id param") + } + + uri := fmt.Sprintf("%s/asset/%s/%s", openseaURL, req.ContractAddress, req.TokenId) + + var resp domain.Asset + + if err := api.Get(uri, &resp); err != nil { + return errors.InternalServerError("nft.collection", "failed to get collection: %v", err) + } + + rsp.Asset = assetToPb(&resp) + + return nil +} + +func (o *OpenSea) Collection(ctx context.Context, req *pb.CollectionRequest, rsp *pb.CollectionResponse) error { + if len(req.Slug) == 0 { + return errors.BadRequest("nft.collection", "Missing slug param") + } + + uri := fmt.Sprintf("%s/collection/%s", openseaURL, req.Slug) + + var resp domain.CollectionResponse + + if err := api.Get(uri, &resp); err != nil { + return errors.InternalServerError("nft.collection", "failed to get collection: %v", err) + } + + rsp.Collection = collectionToPb(resp.Collection) + + return nil +} diff --git a/nft/proto/nft.pb.go b/nft/proto/nft.pb.go index b889b1b..4f9167a 100644 --- a/nft/proto/nft.pb.go +++ b/nft/proto/nft.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.15.6 +// protoc-gen-go v1.26.0 +// protoc v3.15.5 // source: proto/nft.proto package nft @@ -9,6 +9,7 @@ package nft import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + structpb "google.golang.org/protobuf/types/known/structpb" reflect "reflect" sync "sync" ) @@ -279,6 +280,8 @@ type Asset struct { LastSale *Sale `protobuf:"bytes,13,opt,name=last_sale,json=lastSale,proto3" json:"last_sale,omitempty"` // listing date ListingDate string `protobuf:"bytes,14,opt,name=listing_date,json=listingDate,proto3" json:"listing_date,omitempty"` + // traits associated with the item + Traits []*structpb.Struct `protobuf:"bytes,15,rep,name=traits,proto3" json:"traits,omitempty"` } func (x *Asset) Reset() { @@ -411,6 +414,13 @@ func (x *Asset) GetListingDate() string { return "" } +func (x *Asset) GetTraits() []*structpb.Struct { + if x != nil { + return x.Traits + } + return nil +} + type Contract struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -545,12 +555,36 @@ type Collection struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - Slug string `protobuf:"bytes,3,opt,name=slug,proto3" json:"slug,omitempty"` - ImageUrl string `protobuf:"bytes,4,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` - CreatedAt string `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + // name of the collection + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + // description of the collection + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + // collection slug + Slug string `protobuf:"bytes,3,opt,name=slug,proto3" json:"slug,omitempty"` + // an image for the collection + ImageUrl string `protobuf:"bytes,4,opt,name=image_url,json=imageUrl,proto3" json:"image_url,omitempty"` + // creation time + CreatedAt string `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + // payout address for the collection's royalties PayoutAddress string `protobuf:"bytes,6,opt,name=payout_address,json=payoutAddress,proto3" json:"payout_address,omitempty"` + // external link to the original website for the collection + ExternalLink string `protobuf:"bytes,7,opt,name=external_link,json=externalLink,proto3" json:"external_link,omitempty"` + // image used in the banner for the collection + BannerImageUrl string `protobuf:"bytes,8,opt,name=banner_image_url,json=bannerImageUrl,proto3" json:"banner_image_url,omitempty"` + // the fees that get paid out when a sale is made + SellerFees string `protobuf:"bytes,9,opt,name=seller_fees,json=sellerFees,proto3" json:"seller_fees,omitempty"` + // the collection's approval status on OpenSea + SafelistRequestStatus string `protobuf:"bytes,10,opt,name=safelist_request_status,json=safelistRequestStatus,proto3" json:"safelist_request_status,omitempty"` + // a list of the contracts associated with this collection + PrimaryAssetContracts []*Contract `protobuf:"bytes,11,rep,name=primary_asset_contracts,json=primaryAssetContracts,proto3" json:"primary_asset_contracts,omitempty"` + // listing of all the trait types available within this collection + Traits *structpb.Struct `protobuf:"bytes,12,opt,name=traits,proto3" json:"traits,omitempty"` + // the payment tokens accepted for this collection + PaymentTokens []*Token `protobuf:"bytes,13,rep,name=payment_tokens,json=paymentTokens,proto3" json:"payment_tokens,omitempty"` + // approved editors for this collection + Editors []string `protobuf:"bytes,14,rep,name=editors,proto3" json:"editors,omitempty"` + // sales statistics associated with the collection + Stats *structpb.Struct `protobuf:"bytes,15,opt,name=stats,proto3" json:"stats,omitempty"` } func (x *Collection) Reset() { @@ -627,6 +661,69 @@ func (x *Collection) GetPayoutAddress() string { return "" } +func (x *Collection) GetExternalLink() string { + if x != nil { + return x.ExternalLink + } + return "" +} + +func (x *Collection) GetBannerImageUrl() string { + if x != nil { + return x.BannerImageUrl + } + return "" +} + +func (x *Collection) GetSellerFees() string { + if x != nil { + return x.SellerFees + } + return "" +} + +func (x *Collection) GetSafelistRequestStatus() string { + if x != nil { + return x.SafelistRequestStatus + } + return "" +} + +func (x *Collection) GetPrimaryAssetContracts() []*Contract { + if x != nil { + return x.PrimaryAssetContracts + } + return nil +} + +func (x *Collection) GetTraits() *structpb.Struct { + if x != nil { + return x.Traits + } + return nil +} + +func (x *Collection) GetPaymentTokens() []*Token { + if x != nil { + return x.PaymentTokens + } + return nil +} + +func (x *Collection) GetEditors() []string { + if x != nil { + return x.Editors + } + return nil +} + +func (x *Collection) GetStats() *structpb.Struct { + if x != nil { + return x.Stats + } + return nil +} + type User struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1007,7 +1104,7 @@ func (x *Token) GetUsdPrice() string { return "" } -// Return a list of NFT assets +// Return a list of assets type AssetsRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1140,173 +1237,423 @@ func (x *AssetsResponse) GetAssets() []*Asset { return nil } +type AssetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ContractAddress string `protobuf:"bytes,1,opt,name=contract_address,json=contractAddress,proto3" json:"contract_address,omitempty"` + TokenId string `protobuf:"bytes,2,opt,name=token_id,json=tokenId,proto3" json:"token_id,omitempty"` +} + +func (x *AssetRequest) Reset() { + *x = AssetRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_nft_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AssetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AssetRequest) ProtoMessage() {} + +func (x *AssetRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_nft_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AssetRequest.ProtoReflect.Descriptor instead. +func (*AssetRequest) Descriptor() ([]byte, []int) { + return file_proto_nft_proto_rawDescGZIP(), []int{13} +} + +func (x *AssetRequest) GetContractAddress() string { + if x != nil { + return x.ContractAddress + } + return "" +} + +func (x *AssetRequest) GetTokenId() string { + if x != nil { + return x.TokenId + } + return "" +} + +type AssetResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Asset *Asset `protobuf:"bytes,1,opt,name=asset,proto3" json:"asset,omitempty"` +} + +func (x *AssetResponse) Reset() { + *x = AssetResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_nft_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AssetResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AssetResponse) ProtoMessage() {} + +func (x *AssetResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_nft_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AssetResponse.ProtoReflect.Descriptor instead. +func (*AssetResponse) Descriptor() ([]byte, []int) { + return file_proto_nft_proto_rawDescGZIP(), []int{14} +} + +func (x *AssetResponse) GetAsset() *Asset { + if x != nil { + return x.Asset + } + return nil +} + +type CollectionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Slug string `protobuf:"bytes,1,opt,name=slug,proto3" json:"slug,omitempty"` +} + +func (x *CollectionRequest) Reset() { + *x = CollectionRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_nft_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CollectionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CollectionRequest) ProtoMessage() {} + +func (x *CollectionRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_nft_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CollectionRequest.ProtoReflect.Descriptor instead. +func (*CollectionRequest) Descriptor() ([]byte, []int) { + return file_proto_nft_proto_rawDescGZIP(), []int{15} +} + +func (x *CollectionRequest) GetSlug() string { + if x != nil { + return x.Slug + } + return "" +} + +type CollectionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Collection *Collection `protobuf:"bytes,1,opt,name=collection,proto3" json:"collection,omitempty"` +} + +func (x *CollectionResponse) Reset() { + *x = CollectionResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_nft_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CollectionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CollectionResponse) ProtoMessage() {} + +func (x *CollectionResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_nft_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CollectionResponse.ProtoReflect.Descriptor instead. +func (*CollectionResponse) Descriptor() ([]byte, []int) { + return file_proto_nft_proto_rawDescGZIP(), []int{16} +} + +func (x *CollectionResponse) GetCollection() *Collection { + if x != nil { + return x.Collection + } + return nil +} + var File_proto_nft_proto protoreflect.FileDescriptor var file_proto_nft_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6e, 0x66, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x03, 0x6e, 0x66, 0x74, 0x22, 0x6f, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, - 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x69, 0x6d, - 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x32, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x05, 0x61, 0x73, 0x73, - 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x41, - 0x73, 0x73, 0x65, 0x74, 0x52, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x22, 0x42, 0x0a, 0x12, 0x43, - 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, - 0x48, 0x0a, 0x13, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6e, 0x66, - 0x74, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x63, 0x6f, - 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xc0, 0x03, 0x0a, 0x05, 0x41, 0x73, - 0x73, 0x65, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, - 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x72, - 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x61, 0x6c, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x05, 0x73, 0x61, 0x6c, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, - 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, - 0x61, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x29, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, - 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, - 0x12, 0x2f, 0x0a, 0x0a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x23, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x07, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, - 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x73, 0x61, - 0x6c, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x72, 0x65, 0x73, 0x61, 0x6c, - 0x65, 0x12, 0x26, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x61, 0x6c, 0x65, 0x18, 0x0d, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x53, 0x61, 0x6c, 0x65, 0x52, - 0x08, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x69, 0x73, - 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x6c, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x61, 0x74, 0x65, 0x22, 0x9b, 0x02, 0x0a, - 0x08, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, - 0x6e, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6d, 0x62, - 0x6f, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, + 0x6f, 0x12, 0x03, 0x6e, 0x66, 0x74, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6f, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x69, + 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x32, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x20, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x52, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x22, 0x42, 0x0a, 0x12, 0x43, 0x6f, 0x6c, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, + 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x48, 0x0a, + 0x13, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x31, 0x0a, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6e, 0x66, 0x74, 0x2e, + 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xf1, 0x03, 0x0a, 0x05, 0x41, 0x73, 0x73, 0x65, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x6f, - 0x75, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6c, - 0x6c, 0x65, 0x72, 0x5f, 0x66, 0x65, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x46, 0x65, 0x65, 0x73, 0x22, 0xb9, 0x01, 0x0a, 0x0a, 0x43, - 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, - 0x6c, 0x75, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, 0x6c, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x72, 0x6c, - 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, - 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x41, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x5d, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1a, - 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, - 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0xdc, 0x02, 0x0a, 0x04, 0x53, 0x61, 0x6c, 0x65, 0x12, 0x24, - 0x0a, 0x0e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x64, 0x65, - 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x73, - 0x73, 0x65, 0x74, 0x44, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x69, - 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, - 0x72, 0x69, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, - 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, - 0x32, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x0d, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, - 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x66, 0x74, - 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0c, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x54, - 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xad, 0x02, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, - 0x68, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, - 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x0c, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x61, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x6e, 0x66, 0x74, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x41, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x0a, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x09, 0x74, 0x6f, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, - 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x48, 0x61, 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x22, 0xd0, 0x01, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, - 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x72, - 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x08, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, 0x1b, 0x0a, - 0x09, 0x65, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x65, 0x74, 0x68, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, - 0x64, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, - 0x73, 0x64, 0x50, 0x72, 0x69, 0x63, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x0d, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, - 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, - 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x19, 0x0a, - 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6c, 0x6c, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, - 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x34, 0x0a, 0x0e, 0x41, 0x73, 0x73, 0x65, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x06, 0x61, 0x73, - 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x66, 0x74, - 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x32, 0xb3, - 0x01, 0x0a, 0x03, 0x4e, 0x66, 0x74, 0x12, 0x33, 0x0a, 0x06, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, - 0x12, 0x12, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x06, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x12, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6e, 0x66, 0x74, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x42, 0x0a, 0x0b, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x17, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, - 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x42, 0x0d, 0x5a, 0x0b, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, - 0x6e, 0x66, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x72, 0x6c, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x61, 0x6c, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, + 0x73, 0x61, 0x6c, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, 0x69, + 0x6e, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x65, 0x72, 0x6d, 0x61, 0x6c, + 0x69, 0x6e, 0x6b, 0x12, 0x29, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x2f, + 0x0a, 0x0a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x23, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x09, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x07, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x6f, 0x72, 0x12, 0x1f, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x65, 0x73, 0x61, 0x6c, 0x65, + 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x70, 0x72, 0x65, 0x73, 0x61, 0x6c, 0x65, 0x12, + 0x26, 0x0a, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x61, 0x6c, 0x65, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x53, 0x61, 0x6c, 0x65, 0x52, 0x08, 0x6c, + 0x61, 0x73, 0x74, 0x53, 0x61, 0x6c, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x69, 0x73, 0x74, 0x69, + 0x6e, 0x67, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6c, + 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x74, 0x72, + 0x61, 0x69, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x52, 0x06, 0x74, 0x72, 0x61, 0x69, 0x74, 0x73, 0x22, 0x9b, 0x02, 0x0a, 0x08, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, + 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x12, + 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x6f, 0x75, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6c, 0x6c, + 0x65, 0x72, 0x5f, 0x66, 0x65, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, + 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x46, 0x65, 0x65, 0x73, 0x22, 0xd5, 0x04, 0x0a, 0x0a, 0x43, 0x6f, + 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, + 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, + 0x75, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x72, 0x6c, 0x12, + 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x25, + 0x0a, 0x0e, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x78, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x28, 0x0a, 0x10, 0x62, 0x61, + 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x62, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, + 0x65, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x6c, 0x6c, 0x65, 0x72, 0x5f, 0x66, + 0x65, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x6c, 0x6c, 0x65, + 0x72, 0x46, 0x65, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x73, 0x61, 0x66, 0x65, 0x6c, 0x69, 0x73, + 0x74, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x73, 0x61, 0x66, 0x65, 0x6c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x45, 0x0a, + 0x17, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x52, 0x15, 0x70, + 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x41, 0x73, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x73, 0x12, 0x2f, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x69, 0x74, 0x73, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x06, 0x74, + 0x72, 0x61, 0x69, 0x74, 0x73, 0x12, 0x31, 0x0a, 0x0e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, + 0x6e, 0x66, 0x74, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x0d, 0x70, 0x61, 0x79, 0x6d, 0x65, + 0x6e, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x64, 0x69, 0x74, + 0x6f, 0x72, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x65, 0x64, 0x69, 0x74, 0x6f, + 0x72, 0x73, 0x12, 0x2d, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x73, 0x22, 0x5d, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, + 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, + 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, + 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x66, + 0x69, 0x6c, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x22, 0xdc, 0x02, 0x0a, 0x04, 0x53, 0x61, 0x6c, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x64, 0x12, + 0x25, 0x0a, 0x0e, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x44, 0x65, + 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1f, + 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, + 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x71, 0x75, 0x61, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x32, 0x0a, 0x0b, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2f, + 0x0a, 0x0d, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x52, 0x0c, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, + 0xad, 0x02, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1d, 0x0a, + 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x21, 0x0a, 0x0c, + 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, + 0x2c, 0x0a, 0x0c, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x52, 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, + 0x0a, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x09, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x09, 0x74, 0x6f, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x74, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x61, + 0x73, 0x68, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x22, + 0xd0, 0x01, 0x0a, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x73, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, + 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, + 0x1b, 0x0a, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, + 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, + 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x65, 0x74, 0x68, 0x5f, + 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x74, 0x68, + 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x64, 0x5f, 0x70, 0x72, 0x69, + 0x63, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x64, 0x50, 0x72, 0x69, + 0x63, 0x65, 0x22, 0x8e, 0x01, 0x0a, 0x0d, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, + 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, + 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x5f, 0x62, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x42, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0x34, 0x0a, 0x0e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x65, + 0x74, 0x52, 0x06, 0x61, 0x73, 0x73, 0x65, 0x74, 0x73, 0x22, 0x54, 0x0a, 0x0c, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x64, 0x22, + 0x31, 0x0a, 0x0d, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x20, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0a, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x05, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x22, 0x27, 0x0a, 0x11, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x22, 0x45, 0x0a, 0x12, 0x43, + 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2f, 0x0a, 0x0a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x32, 0xa6, 0x02, 0x0a, 0x03, 0x4e, 0x66, 0x74, 0x12, 0x33, 0x0a, 0x06, 0x41, 0x73, + 0x73, 0x65, 0x74, 0x73, 0x12, 0x12, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x33, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x12, 0x2e, 0x6e, 0x66, 0x74, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, + 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x00, 0x12, 0x42, 0x0a, 0x0b, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x17, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x6e, + 0x66, 0x74, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x30, 0x0a, 0x05, 0x41, 0x73, 0x73, 0x65, + 0x74, 0x12, 0x11, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x41, 0x73, 0x73, 0x65, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0a, 0x43, 0x6f, + 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, + 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x17, 0x2e, 0x6e, 0x66, 0x74, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x0d, 0x5a, 0x0b, 0x2e, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x3b, 0x6e, 0x66, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1321,7 +1668,7 @@ func file_proto_nft_proto_rawDescGZIP() []byte { return file_proto_nft_proto_rawDescData } -var file_proto_nft_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_proto_nft_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_proto_nft_proto_goTypes = []interface{}{ (*CreateRequest)(nil), // 0: nft.CreateRequest (*CreateResponse)(nil), // 1: nft.CreateResponse @@ -1336,6 +1683,11 @@ var file_proto_nft_proto_goTypes = []interface{}{ (*Token)(nil), // 10: nft.Token (*AssetsRequest)(nil), // 11: nft.AssetsRequest (*AssetsResponse)(nil), // 12: nft.AssetsResponse + (*AssetRequest)(nil), // 13: nft.AssetRequest + (*AssetResponse)(nil), // 14: nft.AssetResponse + (*CollectionRequest)(nil), // 15: nft.CollectionRequest + (*CollectionResponse)(nil), // 16: nft.CollectionResponse + (*structpb.Struct)(nil), // 17: google.protobuf.Struct } var file_proto_nft_proto_depIdxs = []int32{ 4, // 0: nft.CreateResponse.asset:type_name -> nft.Asset @@ -1345,22 +1697,33 @@ var file_proto_nft_proto_depIdxs = []int32{ 7, // 4: nft.Asset.creator:type_name -> nft.User 7, // 5: nft.Asset.owner:type_name -> nft.User 8, // 6: nft.Asset.last_sale:type_name -> nft.Sale - 9, // 7: nft.Sale.transaction:type_name -> nft.Transaction - 10, // 8: nft.Sale.payment_token:type_name -> nft.Token - 7, // 9: nft.Transaction.from_account:type_name -> nft.User - 7, // 10: nft.Transaction.to_account:type_name -> nft.User - 4, // 11: nft.AssetsResponse.assets:type_name -> nft.Asset - 11, // 12: nft.Nft.Assets:input_type -> nft.AssetsRequest - 0, // 13: nft.Nft.Create:input_type -> nft.CreateRequest - 2, // 14: nft.Nft.Collections:input_type -> nft.CollectionsRequest - 12, // 15: nft.Nft.Assets:output_type -> nft.AssetsResponse - 1, // 16: nft.Nft.Create:output_type -> nft.CreateResponse - 3, // 17: nft.Nft.Collections:output_type -> nft.CollectionsResponse - 15, // [15:18] is the sub-list for method output_type - 12, // [12:15] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 17, // 7: nft.Asset.traits:type_name -> google.protobuf.Struct + 5, // 8: nft.Collection.primary_asset_contracts:type_name -> nft.Contract + 17, // 9: nft.Collection.traits:type_name -> google.protobuf.Struct + 10, // 10: nft.Collection.payment_tokens:type_name -> nft.Token + 17, // 11: nft.Collection.stats:type_name -> google.protobuf.Struct + 9, // 12: nft.Sale.transaction:type_name -> nft.Transaction + 10, // 13: nft.Sale.payment_token:type_name -> nft.Token + 7, // 14: nft.Transaction.from_account:type_name -> nft.User + 7, // 15: nft.Transaction.to_account:type_name -> nft.User + 4, // 16: nft.AssetsResponse.assets:type_name -> nft.Asset + 4, // 17: nft.AssetResponse.asset:type_name -> nft.Asset + 6, // 18: nft.CollectionResponse.collection:type_name -> nft.Collection + 11, // 19: nft.Nft.Assets:input_type -> nft.AssetsRequest + 0, // 20: nft.Nft.Create:input_type -> nft.CreateRequest + 2, // 21: nft.Nft.Collections:input_type -> nft.CollectionsRequest + 13, // 22: nft.Nft.Asset:input_type -> nft.AssetRequest + 15, // 23: nft.Nft.Collection:input_type -> nft.CollectionRequest + 12, // 24: nft.Nft.Assets:output_type -> nft.AssetsResponse + 1, // 25: nft.Nft.Create:output_type -> nft.CreateResponse + 3, // 26: nft.Nft.Collections:output_type -> nft.CollectionsResponse + 14, // 27: nft.Nft.Asset:output_type -> nft.AssetResponse + 16, // 28: nft.Nft.Collection:output_type -> nft.CollectionResponse + 24, // [24:29] is the sub-list for method output_type + 19, // [19:24] is the sub-list for method input_type + 19, // [19:19] is the sub-list for extension type_name + 19, // [19:19] is the sub-list for extension extendee + 0, // [0:19] is the sub-list for field type_name } func init() { file_proto_nft_proto_init() } @@ -1525,6 +1888,54 @@ func file_proto_nft_proto_init() { return nil } } + file_proto_nft_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AssetRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_nft_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AssetResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_nft_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CollectionRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_nft_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CollectionResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1532,7 +1943,7 @@ func file_proto_nft_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_nft_proto_rawDesc, NumEnums: 0, - NumMessages: 13, + NumMessages: 17, NumExtensions: 0, NumServices: 1, }, diff --git a/nft/proto/nft.pb.micro.go b/nft/proto/nft.pb.micro.go index b2f8037..62d7679 100644 --- a/nft/proto/nft.pb.micro.go +++ b/nft/proto/nft.pb.micro.go @@ -6,6 +6,7 @@ package nft import ( fmt "fmt" proto "github.com/golang/protobuf/proto" + _ "google.golang.org/protobuf/types/known/structpb" math "math" ) @@ -45,6 +46,8 @@ type NftService interface { Assets(ctx context.Context, in *AssetsRequest, opts ...client.CallOption) (*AssetsResponse, error) Create(ctx context.Context, in *CreateRequest, opts ...client.CallOption) (*CreateResponse, error) Collections(ctx context.Context, in *CollectionsRequest, opts ...client.CallOption) (*CollectionsResponse, error) + Asset(ctx context.Context, in *AssetRequest, opts ...client.CallOption) (*AssetResponse, error) + Collection(ctx context.Context, in *CollectionRequest, opts ...client.CallOption) (*CollectionResponse, error) } type nftService struct { @@ -89,12 +92,34 @@ func (c *nftService) Collections(ctx context.Context, in *CollectionsRequest, op return out, nil } +func (c *nftService) Asset(ctx context.Context, in *AssetRequest, opts ...client.CallOption) (*AssetResponse, error) { + req := c.c.NewRequest(c.name, "Nft.Asset", in) + out := new(AssetResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *nftService) Collection(ctx context.Context, in *CollectionRequest, opts ...client.CallOption) (*CollectionResponse, error) { + req := c.c.NewRequest(c.name, "Nft.Collection", in) + out := new(CollectionResponse) + err := c.c.Call(ctx, req, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // Server API for Nft service type NftHandler interface { Assets(context.Context, *AssetsRequest, *AssetsResponse) error Create(context.Context, *CreateRequest, *CreateResponse) error Collections(context.Context, *CollectionsRequest, *CollectionsResponse) error + Asset(context.Context, *AssetRequest, *AssetResponse) error + Collection(context.Context, *CollectionRequest, *CollectionResponse) error } func RegisterNftHandler(s server.Server, hdlr NftHandler, opts ...server.HandlerOption) error { @@ -102,6 +127,8 @@ func RegisterNftHandler(s server.Server, hdlr NftHandler, opts ...server.Handler Assets(ctx context.Context, in *AssetsRequest, out *AssetsResponse) error Create(ctx context.Context, in *CreateRequest, out *CreateResponse) error Collections(ctx context.Context, in *CollectionsRequest, out *CollectionsResponse) error + Asset(ctx context.Context, in *AssetRequest, out *AssetResponse) error + Collection(ctx context.Context, in *CollectionRequest, out *CollectionResponse) error } type Nft struct { nft @@ -125,3 +152,11 @@ func (h *nftHandler) Create(ctx context.Context, in *CreateRequest, out *CreateR func (h *nftHandler) Collections(ctx context.Context, in *CollectionsRequest, out *CollectionsResponse) error { return h.NftHandler.Collections(ctx, in, out) } + +func (h *nftHandler) Asset(ctx context.Context, in *AssetRequest, out *AssetResponse) error { + return h.NftHandler.Asset(ctx, in, out) +} + +func (h *nftHandler) Collection(ctx context.Context, in *CollectionRequest, out *CollectionResponse) error { + return h.NftHandler.Collection(ctx, in, out) +} diff --git a/nft/proto/nft.proto b/nft/proto/nft.proto index b15e840..c608b9b 100644 --- a/nft/proto/nft.proto +++ b/nft/proto/nft.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +import "google/protobuf/struct.proto"; + package nft; option go_package = "./proto;nft"; @@ -8,6 +10,8 @@ service Nft { rpc Assets(AssetsRequest) returns (AssetsResponse) {} rpc Create(CreateRequest) returns (CreateResponse) {} rpc Collections(CollectionsRequest) returns (CollectionsResponse) {} + rpc Asset(AssetRequest) returns (AssetResponse) {} + rpc Collection(CollectionRequest) returns (CollectionResponse) {} } // Create your own NFT (coming soon) @@ -65,6 +69,8 @@ message Asset { Sale last_sale = 13; // listing date string listing_date = 14; + // traits associated with the item + repeated google.protobuf.Struct traits = 15; } message Contract { @@ -91,12 +97,36 @@ message Contract { } message Collection { + // name of the collection string name = 1; + // description of the collection string description = 2; + // collection slug string slug = 3; + // an image for the collection string image_url = 4; + // creation time string created_at = 5; + // payout address for the collection's royalties string payout_address = 6; + // external link to the original website for the collection + string external_link = 7; + // image used in the banner for the collection + string banner_image_url = 8; + // the fees that get paid out when a sale is made + string seller_fees = 9; + // the collection's approval status on OpenSea + string safelist_request_status = 10; + // a list of the contracts associated with this collection + repeated Contract primary_asset_contracts = 11; + // listing of all the trait types available within this collection + google.protobuf.Struct traits = 12; + // the payment tokens accepted for this collection + repeated Token payment_tokens = 13; + // approved editors for this collection + repeated string editors = 14; + // sales statistics associated with the collection + google.protobuf.Struct stats = 15; } message User { @@ -157,3 +187,20 @@ message AssetsResponse { // list of assets repeated Asset assets = 1; } + +message AssetRequest { + string contract_address = 1; + string token_id = 2; +} + +message AssetResponse { + Asset asset = 1; +} + +message CollectionRequest { + string slug = 1; +} + +message CollectionResponse { + Collection collection = 1; +}