Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat-hack-wasm-berlin #285

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,9 @@ target/
*.lcov
lcov.info
contracts/*/schema/
debug/
artifacts/
Cargo.lock
**/*.rs.bk
*.pdb
**/state.local.json
1 change: 1 addition & 0 deletions Beaker.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
name = "frontend"
11 changes: 11 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,14 @@ schemars = "0.8.12"
serde = { version = "1.0.168", default-features = false, features = ["derive"] }
serde-json-wasm = "0.5.1"
thiserror = { version = "1.0.43" }

[profile.release]
codegen-units = 1
debug = false
debug-assertions = false
incremental = false
lto = true
opt-level = 3
overflow-checks = true
panic = 'abort'
rpath = false
5 changes: 5 additions & 0 deletions contracts/okp4-cw721/.cargo/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[alias]
wasm = "build --release --target wasm32-unknown-unknown"
wasm-debug = "build --target wasm32-unknown-unknown"
unit-test = "test --lib"
schema = "run --example schema"
31 changes: 31 additions & 0 deletions contracts/okp4-cw721/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "cw721-metadata-onchain"
description = "Example extending CW721 NFT to store metadata on chain"
authors = [
"Ethan Frey <[email protected]>",
"Orkun Külçe <[email protected]>",
]
version = { workspace = true }
edition = { workspace = true }
license = { workspace = true }
repository = { workspace = true }
homepage = { workspace = true }
documentation = { workspace = true }

[lib]
crate-type = ["cdylib", "rlib"]

[features]
# for more explicit tests, cargo test --features=backtraces
backtraces = ["cosmwasm-std/backtraces"]
# use library feature to disable all instantiate/execute/query exports
library = []

[dependencies]
cosmwasm-schema = { workspace = true }
cosmwasm-std = { workspace = true }
cw2 = { workspace = true }
cw721 = { workspace = true }
cw721-base = { workspace = true, features = ["library"] }
schemars = { workspace = true }
serde = { workspace = true }
14 changes: 14 additions & 0 deletions contracts/okp4-cw721/NOTICE
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Cw721_metadata_onchain
Copyright (C) 2021 Confio OÜ

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
64 changes: 64 additions & 0 deletions contracts/okp4-cw721/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# CW721 Metadata Onchain

NFT creators may want to store their NFT metadata on-chain so other contracts are able to interact with it.
With CW721-Base in CosmWasm, we allow you to store any data on chain you wish, using a generic `extension: T`.

In order to support on-chain metadata, and to demonstrate how to use the extension ability, we have created this simple contract.
There is no business logic here, but looking at `lib.rs` will show you how do define custom data that is included when minting and
available in all queries.

In particular, here we define:

```rust
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct Trait {
pub display_type: Option<String>,
pub trait_type: String,
pub value: String,
}

#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct Metadata {
pub image: Option<String>,
pub image_data: Option<String>,
pub external_url: Option<String>,
pub description: Option<String>,
pub name: Option<String>,
pub attributes: Option<Vec<Trait>>,
pub background_color: Option<String>,
pub animation_url: Option<String>,
pub youtube_url: Option<String>,
}

pub type Extension = Option<Metadata>;
```

In particular, the fields defined conform to the properties supported in the [OpenSea Metadata Standard](https://docs.opensea.io/docs/metadata-standards).


This means when you query `NftInfo{name: "Enterprise"}`, you will get something like:

```json
{
"name": "Enterprise",
"token_uri": "https://starships.example.com/Starship/Enterprise.json",
"extension": {
"image": null,
"image_data": null,
"external_url": null,
"description": "Spaceship with Warp Drive",
"name": "Starship USS Enterprise",
"attributes": null,
"background_color": null,
"animation_url": null,
"youtube_url": null
}
}
```

Please look at the test code for an example usage in Rust.

## Notice

Feel free to use this contract out of the box, or as inspiration for further customization of cw721-base.
We will not be adding new features or business logic here.
11 changes: 11 additions & 0 deletions contracts/okp4-cw721/examples/schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use cosmwasm_schema::write_api;

use cw721_metadata_onchain::{ExecuteMsg, InstantiateMsg, QueryMsg};

fn main() {
write_api! {
instantiate: InstantiateMsg,
execute: ExecuteMsg,
query: QueryMsg,
}
}
141 changes: 141 additions & 0 deletions contracts/okp4-cw721/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Empty;
pub use cw721_base::{ContractError, InstantiateMsg, MinterResponse};

// Version info for migration
const CONTRACT_NAME: &str = "crates.io:cw721-metadata-onchain";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

#[cw_serde]
pub struct Trait {
pub display_type: Option<String>,
pub trait_type: String,
pub value: String,
}

// see: https://docs.opensea.io/docs/metadata-standards
#[cw_serde]
#[derive(Default)]
pub struct Metadata {
pub image: Option<String>,
pub image_data: Option<String>,
pub external_url: Option<String>,
pub description: Option<String>,
pub name: Option<String>,
pub attributes: Option<Vec<Trait>>,
pub background_color: Option<String>,
pub animation_url: Option<String>,
pub youtube_url: Option<String>,
}

pub type Extension = Option<Metadata>;

pub type Cw721MetadataContract<'a> = cw721_base::Cw721Contract<'a, Extension, Empty, Empty, Empty>;
pub type ExecuteMsg = cw721_base::ExecuteMsg<Extension, Empty>;
pub type QueryMsg = cw721_base::QueryMsg<Empty>;

#[cfg(not(feature = "library"))]
pub mod entry {
use super::*;

use cosmwasm_std::entry_point;
use cosmwasm_std::{Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult};

// This makes a conscious choice on the various generics used by the contract
#[entry_point]
pub fn instantiate(
mut deps: DepsMut,
env: Env,
info: MessageInfo,
msg: InstantiateMsg,
) -> StdResult<Response> {
cw2::set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

Cw721MetadataContract::default().instantiate(deps.branch(), env, info, msg)
}

#[entry_point]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
Cw721MetadataContract::default().execute(deps, env, info, msg)
}

#[entry_point]
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
Cw721MetadataContract::default().query(deps, env, msg)
}
}

#[cfg(test)]
mod tests {
use super::*;

use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cw721::Cw721Query;

const CREATOR: &str = "creator";

/// Make sure cw2 version info is properly initialized during instantiation,
/// and NOT overwritten by the base contract.
#[test]
fn proper_cw2_initialization() {
let mut deps = mock_dependencies();

entry::instantiate(
deps.as_mut(),
mock_env(),
mock_info("larry", &[]),
InstantiateMsg {
name: "".into(),
symbol: "".into(),
minter: "larry".into(),
},
)
.unwrap();

let version = cw2::get_contract_version(deps.as_ref().storage).unwrap();
assert_eq!(version.contract, CONTRACT_NAME);
assert_ne!(version.contract, cw721_base::CONTRACT_NAME);
}

#[test]
fn use_metadata_extension() {
let mut deps = mock_dependencies();
let contract = Cw721MetadataContract::default();

let info = mock_info(CREATOR, &[]);
let init_msg = InstantiateMsg {
name: "SpaceShips".to_string(),
symbol: "SPACE".to_string(),
minter: CREATOR.to_string(),
};
contract
.instantiate(deps.as_mut(), mock_env(), info.clone(), init_msg)
.unwrap();

let token_id = "Enterprise";
let token_uri = Some("https://starships.example.com/Starship/Enterprise.json".into());
let extension = Some(Metadata {
description: Some("Spaceship with Warp Drive".into()),
name: Some("Starship USS Enterprise".to_string()),
..Metadata::default()
});
let exec_msg = ExecuteMsg::Mint {
token_id: token_id.to_string(),
owner: "john".to_string(),
token_uri: token_uri.clone(),
extension: extension.clone(),
};
contract
.execute(deps.as_mut(), mock_env(), info, exec_msg)
.unwrap();

let res = contract.nft_info(deps.as_ref(), token_id.into()).unwrap();
assert_eq!(res.token_uri, token_uri);
assert_eq!(res.extension, extension);
}
}
1 change: 1 addition & 0 deletions frontend/.beaker/state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
3 changes: 3 additions & 0 deletions frontend/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NEXT_PUBLIC_NETWORK=mainnet
NEXT_PUBLIC_RPC_ENDPOINT="https://rpc.osmosis.zone"
NEXT_PUBLIC_CHAIN_ID=osmosis-1
3 changes: 3 additions & 0 deletions frontend/.env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NEXT_PUBLIC_NETWORK=testnet
NEXT_PUBLIC_RPC_ENDPOINT="https://rpc-test.osmosis.zone"
NEXT_PUBLIC_CHAIN_ID=osmo-test-4
3 changes: 3 additions & 0 deletions frontend/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
35 changes: 35 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
34 changes: 34 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
Loading