Abehjati/cleanup-cosmwasm (#243)

* Remove unneeded stuff and warnings

* Remove old readme and replaye pyth readme with it

* Fix build issue

* Revert wormhole contract.rs change

* Address review comments

* Address review comments

* Make Readme more clear
This commit is contained in:
Ali Behjati 2022-07-29 12:23:21 +04:30 committed by GitHub
parent bf021010cc
commit f0e88848eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 69 additions and 2351 deletions

View File

@ -5,7 +5,6 @@ FROM cosmwasm/workspace-optimizer:0.12.6@sha256:e6565a5e87c830ef3e8775a9035006b3
COPY cosmwasm/Cargo.lock /code/
COPY cosmwasm/Cargo.toml /code/
COPY cosmwasm/contracts /code/contracts
COPY cosmwasm/packages /code/packages
COPY third_party/pyth/p2w-sdk/rust /third_party/pyth/p2w-sdk/rust
RUN --mount=type=cache,target=/code/target,id=cosmwasm_target --mount=type=cache,target=/usr/local/cargo/registry optimize_workspace.sh

View File

@ -1,45 +1,93 @@
# Deploy
# Pyth CosmWasm
First build the contracts
This directory contains The Pyth contract on CosmWasm and utilities to deploy it in CosmWasm chains.
## Deployment
Deploying the CosmWasm contract has two steps:
1. Upload the code. This step will give you a code id.
2. Either create a new contract or migrate an existing one:
1. Create a new contract that has an address with a code id as its program.
2. Migrating an existing contract code id to the new code id.
This directory includes a script to perform both steps. Read below for the details.
### Uploading the code
First, build the contracts within [the current directory](./):
``` sh
docker build -f Dockerfile.build -o artifacts .
bash build.sh
```
Then, for example, to deploy `token_bridge.wasm`, run in the `tools` directory
This command will build and save the Pyth contract in the `artifact` directory.
Then, to deploy the Pyth contract (`pyth_bridge.wasm`), run the following command in the `tools` directory:
``` sh
npm ci
node deploy_single.js --network mainnet --artifact ../artifacts/token_bridge.wasm --mnemonic "..."
npm ci # Do it only once to install the required packages
npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_bridge.wasm --mnemonic "..."
```
which will print something along the lines of
If successful, this command will print something along the lines of:
``` sh
Storing WASM: ../artifacts/token_bridge.wasm (367689 bytes)
Storing WASM: ../artifacts/pyth_bridge.wasm (367689 bytes)
Deploy fee: 88446uluna
Code ID: 2435
```
# Migrate
If you do not pass any additional arguments to the script, it will only upload the code and return the code id. If you want to create a
new contract or upgrade an existing contract you should pass more arguments that are described below.
## Mainnet
Migrations on mainnet have to go through governance. Once the guardians sign the
upgrade VAA, the contract can be upgraded by submitting the signed VAA to the
appropriate contract. For example, to upgrade the token bridge on mainnet,
in `wormhole/clients/token_bridge/`:
### Instantiating new contract
If you want to instantiate a new contract after your deployment, pass `--instantiate` to the above command.
This command will upload the code and instantiates a new Pyth contract with the resulting code id:
``` sh
node main.js terra execute_governance_vaa <signed VAA (hex)> --rpc "https://lcd.terra.dev" --chain_id "columbus-5" --mnemonic "..." --token_bridge "terra10nmmwe8r3g99a9newtqa7a75xfgs2e8z87r2sf"
npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_bridge.wasm --mnemonic "..." --instantiate
```
## Testnet
If successful, the output should look like so:
```
Storing WASM: ../artifacts/pyth_bridge.wasm (183749 bytes)
Deploy fee: 44682uluna
Code ID: 53199
Instantiating a contract
Sleeping for 10 seconds for store transaction to finalize.
Instantiated Pyth Bridge at terra123456789yelw23uh22nadqlyjvtl7s5527er97 (0x0000000000000000000000001234567896267ee5479752a7d683e49317ff4294)
Deployed Pyth contract at terra123456789yelw23uh22nadqlyjvtl7s5527er97
```
For example, to migrate the token bridge to 37262, run in `tools/`:
### Migrating existing contract
If you want to upgrade an existing contract pass `--migrate --contract terra123456xyzqwe..` to the above command.
This command will upload the code, and with the resulting code id, will migrate the existing contract to the new one:
``` sh
node migrate_testnet.js --code_id 37262 --contract terra1pseddrv0yfsn76u4zxrjmtf45kdlmalswdv39a --mnemonic "..."
npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_bridge.wasm --mnemonic "..." --migrate --contract "terra123..."
```
If successful, the output should look like so:
```
Storing WASM: ../artifacts/pyth_bridge.wasm (183749 bytes)
Deploy fee: 44682uluna
Code ID: 53227
Sleeping for 10 seconds for store transaction to finalize.
Migrating contract terra1rhjej5gkyelw23uh22nadqlyjvtl7s5527er97 to 53227
Contract terra1rhjej5gkyelw23uh22nadqlyjvtl7s5527er97 code_id successfully updated to 53227
```
### Common Errors
While running the instantiation/migration commands you might get the following errors:
- Gateway timeout: This error means that the request timed out. It is good to double check with terra finder as sometimes transactions succeed despite being timed out.
- Account sequence mismatch: Transactions from an account should have an increasing sequence number. This error happens when a transaction from the same sender is not fully synchronized with the terra RPC and an old sequence number is used. This is likely to happen because the deploy script sends two transactions: one to submit the code, and one to do the instantiation/migration.
You can rerun your command if you encounter any of the above errors. If an error occurs after the new code is uploaded, you can avoid re-uploading the code and use the uploaded code for instantiation/migration. You can use the printed code id in the logs
by passing `--code-id <codeId>` instead of `--artifact`. If you do so, the script will skip uploading the code and instantiate/migrate the contract with the given code id.
An example command using an existing code id looks like so:
``` sh
npm run deploy-pyth -- --network testnet --code-id 50123 --mnemonic "..." --migrate --contract "terra123..."
```

View File

@ -1,88 +0,0 @@
# Intro
Deploying a contract in terra consists of two steps:
1. Uploading the code. This step will give you a code id.
2. Optionally create a new contract or migrate an existing one:
1. Creating a new contract which has an address with a code id as its program.
2. Migrating an existing contract code id to the new code id.
This script can do both steps at the same time. Read below for the details.
# Uploading the code
First build the contracts:
``` sh
bash build.sh
```
This command will builds and saves all the contracts in the `artifact` directory.
Then, for example, to deploy `pyth_bridge.wasm`, run in the `tools` directory:
``` sh
npm ci # Do it only once to install required packages
npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_bridge.wasm --mnemonic "..."
```
which will print something along the lines of:
``` sh
Storing WASM: ../artifacts/pyth_bridge.wasm (367689 bytes)
Deploy fee: 88446uluna
Code ID: 2435
```
If you do not pass any additional arguments to the script it will only upload the code and returns the code id. If you want to create a
new contract or upgrade an existing contract you should pass more arguments that are described below.
# Instantiating new contract
If you want instantiate a new contract after your deployment pass `--instantiate` argument to the above command.
It will upload the code and with the resulting code id instantiates a new pyth contract:
``` sh
npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_bridge.wasm --mnemonic "..." --instantiate
```
If successful, the output should look like:
```
Storing WASM: ../artifacts/pyth_bridge.wasm (183749 bytes)
Deploy fee: 44682uluna
Code ID: 53199
Instantiating a contract
Sleeping for 10 seconds for store transaction to finalize.
Instantiated Pyth Bridge at terra123456789yelw23uh22nadqlyjvtl7s5527er97 (0x0000000000000000000000001234567896267ee5479752a7d683e49317ff4294)
Deployed pyth contract at terra123456789yelw23uh22nadqlyjvtl7s5527er97
```
# Migrating existing contract
If you want to upgrade an existing contract pass `--migrate --contract terra123456xyzqwe..` arguments to the above command.
It will upload the code and with the resulting code id migrates the existing contract to the new one:
``` sh
npm run deploy-pyth -- --network testnet --artifact ../artifacts/pyth_bridge.wasm --mnemonic "..." --migrate --contract "terra123..."
```
If successful, the output should look like:
```
Storing WASM: ../artifacts/pyth_bridge.wasm (183749 bytes)
Deploy fee: 44682uluna
Code ID: 53227
Sleeping for 10 seconds for store transaction to finalize.
Migrating contract terra1rhjej5gkyelw23uh22nadqlyjvtl7s5527er97 to 53227
Contract terra1rhjej5gkyelw23uh22nadqlyjvtl7s5527er97 code_id successfully updated to 53227
```
# Notes
You might encounter gateway timeout or account sequence mismatch in errors. In is good to double check with terra finder as sometimes
transactions succeed despite being timed out.
If that happens in the middle of an instantiation or migration. You can avoid re-uploading the code and use the resulting Code Id
by passing `--code-id <codeId>` instead of `--artifact` and it will only do the instantiation/migration part.
An example is:
``` sh
npm run deploy-pyth -- --network testnet --code-id 50123 --mnemonic "..." --migrate --contract "terra123..."
```

View File

@ -391,69 +391,3 @@ impl TransferFee {
Ok(TransferFee { amount, recipient })
}
}
#[cfg(test)]
mod tests {
use super::*;
fn build_guardian_set(length: usize) -> GuardianSetInfo {
let mut addresses: Vec<GuardianAddress> = Vec::with_capacity(length);
for _ in 0..length {
addresses.push(GuardianAddress {
bytes: vec![].into(),
});
}
GuardianSetInfo {
addresses,
expiration_time: 0,
}
}
#[test]
fn quardian_set_quorum() {
assert_eq!(build_guardian_set(1).quorum(), 1);
assert_eq!(build_guardian_set(2).quorum(), 2);
assert_eq!(build_guardian_set(3).quorum(), 3);
assert_eq!(build_guardian_set(4).quorum(), 3);
assert_eq!(build_guardian_set(5).quorum(), 4);
assert_eq!(build_guardian_set(6).quorum(), 5);
assert_eq!(build_guardian_set(7).quorum(), 5);
assert_eq!(build_guardian_set(8).quorum(), 6);
assert_eq!(build_guardian_set(9).quorum(), 7);
assert_eq!(build_guardian_set(10).quorum(), 7);
assert_eq!(build_guardian_set(11).quorum(), 8);
assert_eq!(build_guardian_set(12).quorum(), 9);
assert_eq!(build_guardian_set(20).quorum(), 14);
assert_eq!(build_guardian_set(25).quorum(), 17);
assert_eq!(build_guardian_set(100).quorum(), 67);
}
#[test]
fn test_deserialize() {
let x = hex::decode("080000000901007bfa71192f886ab6819fa4862e34b4d178962958d9b2e3d9437338c9e5fde1443b809d2886eaa69e0f0158ea517675d96243c9209c3fe1d94d5b19866654c6980000000b150000000500020001020304000000000000000000000000000000000000000000000000000000000000000000000a0261626364").unwrap();
let v = ParsedVAA::deserialize(x.as_slice()).unwrap();
assert_eq!(
v,
ParsedVAA {
version: 8,
guardian_set_index: 9,
timestamp: 2837,
nonce: 5,
len_signers: 1,
emitter_chain: 2,
emitter_address: vec![
0, 1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0
],
sequence: 10,
consistency_level: 2,
payload: vec![97, 98, 99, 100],
hash: vec![
195, 10, 19, 96, 8, 61, 218, 69, 160, 238, 165, 142, 105, 119, 139, 121, 212,
73, 238, 179, 13, 80, 245, 224, 75, 110, 163, 8, 185, 132, 55, 34
]
}
);
}
}

View File

@ -1,4 +0,0 @@
[alias]
wasm = "build --release --target wasm32-unknown-unknown"
wasm-debug = "build --target wasm32-unknown-unknown"
schema = "run --example schema"

View File

@ -1,19 +0,0 @@
[package]
name = "cw721"
version = "0.10.1"
authors = ["Ethan Frey <ethanfrey@users.noreply.github.com>"]
edition = "2018"
description = "Definition and types for the CosmWasm-721 NFT interface"
license = "Apache-2.0"
repository = "https://github.com/CosmWasm/cw-nfts"
homepage = "https://cosmwasm.com"
documentation = "https://docs.cosmwasm.com"
[dependencies]
cw0 = { version = "0.8.0" }
cosmwasm-std = { version = "1.0.0" }
schemars = "0.8.6"
serde = { version = "1.0.130", default-features = false, features = ["derive"] }
[dev-dependencies]
cosmwasm-schema = { version = "1.0.0-beta2" }

View File

@ -1,14 +0,0 @@
CW721: A CosmWasm spec for non-fungible token contracts
Copyright (C) 2020-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.

View File

@ -1,122 +0,0 @@
# CW721 Spec: Non Fungible Tokens
CW721 is a specification for non-fungible tokens based on CosmWasm.
The name and design is based on Ethereum's ERC721 standard,
with some enhancements. The types in here can be imported by
contracts that wish to implement this spec, or by contracts that call
to any standard cw721 contract.
The specification is split into multiple sections, a contract may only
implement some of this functionality, but must implement the base.
## Base
This handles ownership, transfers, and allowances. These must be supported
as is by all CW721 contracts. Note that all tokens must have an owner,
as well as an ID. The ID is an arbitrary string, unique within the contract.
### Messages
`TransferNft{recipient, token_id}` -
This transfers ownership of the token to `recipient` account. This is
designed to send to an address controlled by a private key and *does not*
trigger any actions on the recipient if it is a contract.
Requires `token_id` to point to a valid token, and `env.sender` to be
the owner of it, or have an allowance to transfer it.
`SendNft{contract, token_id, msg}` -
This transfers ownership of the token to `contract` account. `contract`
must be an address controlled by a smart contract, which implements
the CW721Receiver interface. The `msg` will be passed to the recipient
contract, along with the token_id.
Requires `token_id` to point to a valid token, and `env.sender` to be
the owner of it, or have an allowance to transfer it.
`Approve{spender, token_id, expires}` - Grants permission to `spender` to
transfer or send the given token. This can only be performed when
`env.sender` is the owner of the given `token_id` or an `operator`.
There can multiple spender accounts per token, and they are cleared once
the token is transfered or sent.
`Revoke{spender, token_id}` - This revokes a previously granted permission
to transfer the given `token_id`. This can only be granted when
`env.sender` is the owner of the given `token_id` or an `operator`.
`ApproveAll{operator, expires}` - Grant `operator` permission to transfer or send
all tokens owned by `env.sender`. This approval is tied to the owner, not the
tokens and applies to any future token that the owner receives as well.
`RevokeAll{operator}` - Revoke a previous `ApproveAll` permission granted
to the given `operator`.
### Queries
`OwnerOf{token_id}` - Returns the owner of the given token,
as well as anyone with approval on this particular token.
If the token is unknown, returns an error. Return type is
`OwnerResponse{owner}`.
`ApprovedForAll{owner, include_expired}` - List all operators that can
access all of the owner's tokens. Return type is `ApprovedForAllResponse`.
If `include_expired` is set, show expired owners in the results, otherwise,
ignore them.
`NumTokens{}` - Total number of tokens issued
### Receiver
The counter-part to `SendNft` is `ReceiveNft`, which must be implemented by
any contract that wishes to manage CW721 tokens. This is generally *not*
implemented by any CW721 contract.
`ReceiveNft{sender, token_id, msg}` - This is designed to handle `SendNft`
messages. The address of the contract is stored in `env.sender`
so it cannot be faked. The contract should ensure the sender matches
the token contract it expects to handle, and not allow arbitrary addresses.
The `sender` is the original account requesting to move the token
and `msg` is a `Binary` data that can be decoded into a contract-specific
message. This can be empty if we have only one default action,
or it may be a `ReceiveMsg` variant to clarify the intention. For example,
if I send to an exchange, I can specify the price I want to list the token
for.
## Metadata
### Queries
`ContractInfo{}` - This returns top-level metadata about the contract.
Namely, `name` and `symbol`.
`NftInfo{token_id}` - This returns metadata about one particular token.
The return value is based on *ERC721 Metadata JSON Schema*, but directly
from the contract, not as a Uri. Only the image link is a Uri.
`AllNftInfo{token_id}` - This returns the result of both `NftInfo`
and `OwnerOf` as one query as an optimization for clients, which may
want both info to display one NFT.
## Enumerable
### Queries
Pagination is acheived via `start_after` and `limit`. Limit is a request
set by the client, if unset, the contract will automatically set it to
`DefaultLimit` (suggested 10). If set, it will be used up to a `MaxLimit`
value (suggested 30). Contracts can define other `DefaultLimit` and `MaxLimit`
values without violating the CW721 spec, and clients should not rely on
any particular values.
If `start_after` is unset, the query returns the first results, ordered by
lexogaphically by `token_id`. If `start_after` is set, then it returns the
first `limit` tokens *after* the given one. This allows straight-forward
pagination by taking the last result returned (a `token_id`) and using it
as the `start_after` value in a future query.
`Tokens{owner, start_after, limit}` - List all token_ids that belong to a given owner.
Return type is `TokensResponse{tokens: Vec<token_id>}`.
`AllTokens{start_after, limit}` - Requires pagination. Lists all token_ids controlled by
the contract.

View File

@ -1,41 +0,0 @@
use std::env::current_dir;
use std::fs::create_dir_all;
use cosmwasm_schema::{export_schema, export_schema_with_title, remove_schemas, schema_for};
use cosmwasm_std::Empty;
use cw721::{
AllNftInfoResponse, ApprovalResponse, ApprovalsResponse, ContractInfoResponse, Cw721ExecuteMsg,
Cw721QueryMsg, Cw721ReceiveMsg, NftInfoResponse, NumTokensResponse, OperatorsResponse,
OwnerOfResponse, TokensResponse,
};
type Extension = Option<Empty>;
fn main() {
let mut out_dir = current_dir().unwrap();
out_dir.push("schema");
create_dir_all(&out_dir).unwrap();
remove_schemas(&out_dir).unwrap();
export_schema(&schema_for!(Cw721ExecuteMsg), &out_dir);
export_schema(&schema_for!(Cw721QueryMsg), &out_dir);
export_schema(&schema_for!(Cw721ReceiveMsg), &out_dir);
export_schema_with_title(
&schema_for!(AllNftInfoResponse<Extension>),
&out_dir,
"AllNftInfoResponse",
);
export_schema(&schema_for!(ApprovalResponse), &out_dir);
export_schema(&schema_for!(ApprovalsResponse), &out_dir);
export_schema(&schema_for!(OperatorsResponse), &out_dir);
export_schema(&schema_for!(ContractInfoResponse), &out_dir);
export_schema(&schema_for!(OwnerOfResponse), &out_dir);
export_schema_with_title(
&schema_for!(NftInfoResponse<Extension>),
&out_dir,
"NftInfoResponse",
);
export_schema(&schema_for!(NumTokensResponse), &out_dir);
export_schema(&schema_for!(TokensResponse), &out_dir);
}

View File

@ -1,155 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "AllNftInfoResponse",
"type": "object",
"required": [
"access",
"info"
],
"properties": {
"access": {
"description": "Who can transfer the token",
"allOf": [
{
"$ref": "#/definitions/OwnerOfResponse"
}
]
},
"info": {
"description": "Data on the token itself,",
"allOf": [
{
"$ref": "#/definitions/NftInfoResponse_for_Nullable_Empty"
}
]
}
},
"definitions": {
"Approval": {
"type": "object",
"required": [
"expires",
"spender"
],
"properties": {
"expires": {
"description": "When the Approval expires (maybe Expiration::never)",
"allOf": [
{
"$ref": "#/definitions/Expiration"
}
]
},
"spender": {
"description": "Account that can transfer/send the token",
"type": "string"
}
}
},
"Empty": {
"description": "An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message.\n\nIt is designed to be expressable in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451)",
"type": "object"
},
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
"oneOf": [
{
"description": "AtHeight will expire when `env.block.height` >= height",
"type": "object",
"required": [
"at_height"
],
"properties": {
"at_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
{
"description": "AtTime will expire when `env.block.time` >= time",
"type": "object",
"required": [
"at_time"
],
"properties": {
"at_time": {
"$ref": "#/definitions/Timestamp"
}
},
"additionalProperties": false
},
{
"description": "Never will never expire. Used to express the empty variant",
"type": "object",
"required": [
"never"
],
"properties": {
"never": {
"type": "object"
}
},
"additionalProperties": false
}
]
},
"NftInfoResponse_for_Nullable_Empty": {
"type": "object",
"properties": {
"extension": {
"description": "You can add any custom metadata here when you extend cw721-base",
"anyOf": [
{
"$ref": "#/definitions/Empty"
},
{
"type": "null"
}
]
},
"token_uri": {
"description": "Universal resource identifier for this NFT Should point to a JSON file that conforms to the ERC721 Metadata JSON Schema",
"type": [
"string",
"null"
]
}
}
},
"OwnerOfResponse": {
"type": "object",
"required": [
"approvals",
"owner"
],
"properties": {
"approvals": {
"description": "If set this address is approved to transfer/send the token as well",
"type": "array",
"items": {
"$ref": "#/definitions/Approval"
}
},
"owner": {
"description": "Owner of the token",
"type": "string"
}
}
},
"Timestamp": {
"description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```",
"allOf": [
{
"$ref": "#/definitions/Uint64"
}
]
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
}
}
}

View File

@ -1,94 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ApprovalResponse",
"type": "object",
"required": [
"approval"
],
"properties": {
"approval": {
"$ref": "#/definitions/Approval"
}
},
"definitions": {
"Approval": {
"type": "object",
"required": [
"expires",
"spender"
],
"properties": {
"expires": {
"description": "When the Approval expires (maybe Expiration::never)",
"allOf": [
{
"$ref": "#/definitions/Expiration"
}
]
},
"spender": {
"description": "Account that can transfer/send the token",
"type": "string"
}
}
},
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
"oneOf": [
{
"description": "AtHeight will expire when `env.block.height` >= height",
"type": "object",
"required": [
"at_height"
],
"properties": {
"at_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
{
"description": "AtTime will expire when `env.block.time` >= time",
"type": "object",
"required": [
"at_time"
],
"properties": {
"at_time": {
"$ref": "#/definitions/Timestamp"
}
},
"additionalProperties": false
},
{
"description": "Never will never expire. Used to express the empty variant",
"type": "object",
"required": [
"never"
],
"properties": {
"never": {
"type": "object"
}
},
"additionalProperties": false
}
]
},
"Timestamp": {
"description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```",
"allOf": [
{
"$ref": "#/definitions/Uint64"
}
]
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
}
}
}

View File

@ -1,97 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ApprovalsResponse",
"type": "object",
"required": [
"approvals"
],
"properties": {
"approvals": {
"type": "array",
"items": {
"$ref": "#/definitions/Approval"
}
}
},
"definitions": {
"Approval": {
"type": "object",
"required": [
"expires",
"spender"
],
"properties": {
"expires": {
"description": "When the Approval expires (maybe Expiration::never)",
"allOf": [
{
"$ref": "#/definitions/Expiration"
}
]
},
"spender": {
"description": "Account that can transfer/send the token",
"type": "string"
}
}
},
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
"oneOf": [
{
"description": "AtHeight will expire when `env.block.height` >= height",
"type": "object",
"required": [
"at_height"
],
"properties": {
"at_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
{
"description": "AtTime will expire when `env.block.time` >= time",
"type": "object",
"required": [
"at_time"
],
"properties": {
"at_time": {
"$ref": "#/definitions/Timestamp"
}
},
"additionalProperties": false
},
{
"description": "Never will never expire. Used to express the empty variant",
"type": "object",
"required": [
"never"
],
"properties": {
"never": {
"type": "object"
}
},
"additionalProperties": false
}
]
},
"Timestamp": {
"description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```",
"allOf": [
{
"$ref": "#/definitions/Uint64"
}
]
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
}
}
}

View File

@ -1,17 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "ContractInfoResponse",
"type": "object",
"required": [
"name",
"symbol"
],
"properties": {
"name": {
"type": "string"
},
"symbol": {
"type": "string"
}
}
}

View File

@ -1,236 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Cw721ExecuteMsg",
"oneOf": [
{
"description": "Transfer is a base message to move a token to another account without triggering actions",
"type": "object",
"required": [
"transfer_nft"
],
"properties": {
"transfer_nft": {
"type": "object",
"required": [
"recipient",
"token_id"
],
"properties": {
"recipient": {
"type": "string"
},
"token_id": {
"type": "string"
}
}
}
},
"additionalProperties": false
},
{
"description": "Send is a base message to transfer a token to a contract and trigger an action on the receiving contract.",
"type": "object",
"required": [
"send_nft"
],
"properties": {
"send_nft": {
"type": "object",
"required": [
"contract",
"msg",
"token_id"
],
"properties": {
"contract": {
"type": "string"
},
"msg": {
"$ref": "#/definitions/Binary"
},
"token_id": {
"type": "string"
}
}
}
},
"additionalProperties": false
},
{
"description": "Allows operator to transfer / send the token from the owner's account. If expiration is set, then this allowance has a time/height limit",
"type": "object",
"required": [
"approve"
],
"properties": {
"approve": {
"type": "object",
"required": [
"spender",
"token_id"
],
"properties": {
"expires": {
"anyOf": [
{
"$ref": "#/definitions/Expiration"
},
{
"type": "null"
}
]
},
"spender": {
"type": "string"
},
"token_id": {
"type": "string"
}
}
}
},
"additionalProperties": false
},
{
"description": "Remove previously granted Approval",
"type": "object",
"required": [
"revoke"
],
"properties": {
"revoke": {
"type": "object",
"required": [
"spender",
"token_id"
],
"properties": {
"spender": {
"type": "string"
},
"token_id": {
"type": "string"
}
}
}
},
"additionalProperties": false
},
{
"description": "Allows operator to transfer / send any token from the owner's account. If expiration is set, then this allowance has a time/height limit",
"type": "object",
"required": [
"approve_all"
],
"properties": {
"approve_all": {
"type": "object",
"required": [
"operator"
],
"properties": {
"expires": {
"anyOf": [
{
"$ref": "#/definitions/Expiration"
},
{
"type": "null"
}
]
},
"operator": {
"type": "string"
}
}
}
},
"additionalProperties": false
},
{
"description": "Remove previously granted ApproveAll permission",
"type": "object",
"required": [
"revoke_all"
],
"properties": {
"revoke_all": {
"type": "object",
"required": [
"operator"
],
"properties": {
"operator": {
"type": "string"
}
}
}
},
"additionalProperties": false
}
],
"definitions": {
"Binary": {
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>",
"type": "string"
},
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
"oneOf": [
{
"description": "AtHeight will expire when `env.block.height` >= height",
"type": "object",
"required": [
"at_height"
],
"properties": {
"at_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
{
"description": "AtTime will expire when `env.block.time` >= time",
"type": "object",
"required": [
"at_time"
],
"properties": {
"at_time": {
"$ref": "#/definitions/Timestamp"
}
},
"additionalProperties": false
},
{
"description": "Never will never expire. Used to express the empty variant",
"type": "object",
"required": [
"never"
],
"properties": {
"never": {
"type": "object"
}
},
"additionalProperties": false
}
]
},
"Timestamp": {
"description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```",
"allOf": [
{
"$ref": "#/definitions/Uint64"
}
]
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
}
}
}

View File

@ -1,240 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Cw721QueryMsg",
"oneOf": [
{
"description": "Return the owner of the given token, error if token does not exist Return type: OwnerOfResponse",
"type": "object",
"required": [
"owner_of"
],
"properties": {
"owner_of": {
"type": "object",
"required": [
"token_id"
],
"properties": {
"include_expired": {
"description": "unset or false will filter out expired approvals, you must set to true to see them",
"type": [
"boolean",
"null"
]
},
"token_id": {
"type": "string"
}
}
}
},
"additionalProperties": false
},
{
"description": "Return operator that can access all of the owner's tokens. Return type: `ApprovedResponse`",
"type": "object",
"required": [
"approved"
],
"properties": {
"approved": {
"type": "object",
"required": [
"operator",
"owner"
],
"properties": {
"operator": {
"type": "string"
},
"owner": {
"type": "string"
}
}
}
},
"additionalProperties": false
},
{
"description": "List all operators that can access all of the owner's tokens. Return type: `ApprovedForAllResponse`",
"type": "object",
"required": [
"approved_for_all"
],
"properties": {
"approved_for_all": {
"type": "object",
"required": [
"owner"
],
"properties": {
"include_expired": {
"description": "unset or false will filter out expired approvals, you must set to true to see them",
"type": [
"boolean",
"null"
]
},
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"owner": {
"type": "string"
},
"start_after": {
"type": [
"string",
"null"
]
}
}
}
},
"additionalProperties": false
},
{
"description": "Total number of tokens issued",
"type": "object",
"required": [
"num_tokens"
],
"properties": {
"num_tokens": {
"type": "object"
}
},
"additionalProperties": false
},
{
"description": "With MetaData Extension. Returns top-level metadata about the contract: `ContractInfoResponse`",
"type": "object",
"required": [
"contract_info"
],
"properties": {
"contract_info": {
"type": "object"
}
},
"additionalProperties": false
},
{
"description": "With MetaData Extension. Returns metadata about one particular token, based on *ERC721 Metadata JSON Schema* but directly from the contract: `NftInfoResponse`",
"type": "object",
"required": [
"nft_info"
],
"properties": {
"nft_info": {
"type": "object",
"required": [
"token_id"
],
"properties": {
"token_id": {
"type": "string"
}
}
}
},
"additionalProperties": false
},
{
"description": "With MetaData Extension. Returns the result of both `NftInfo` and `OwnerOf` as one query as an optimization for clients: `AllNftInfo`",
"type": "object",
"required": [
"all_nft_info"
],
"properties": {
"all_nft_info": {
"type": "object",
"required": [
"token_id"
],
"properties": {
"include_expired": {
"description": "unset or false will filter out expired approvals, you must set to true to see them",
"type": [
"boolean",
"null"
]
},
"token_id": {
"type": "string"
}
}
}
},
"additionalProperties": false
},
{
"description": "With Enumerable extension. Returns all tokens owned by the given address, [] if unset. Return type: TokensResponse.",
"type": "object",
"required": [
"tokens"
],
"properties": {
"tokens": {
"type": "object",
"required": [
"owner"
],
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"owner": {
"type": "string"
},
"start_after": {
"type": [
"string",
"null"
]
}
}
}
},
"additionalProperties": false
},
{
"description": "With Enumerable extension. Requires pagination. Lists all token_ids controlled by the contract. Return type: TokensResponse.",
"type": "object",
"required": [
"all_tokens"
],
"properties": {
"all_tokens": {
"type": "object",
"properties": {
"limit": {
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"start_after": {
"type": [
"string",
"null"
]
}
}
}
},
"additionalProperties": false
}
]
}

View File

@ -1,28 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Cw721ReceiveMsg",
"description": "Cw721ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg",
"type": "object",
"required": [
"msg",
"sender",
"token_id"
],
"properties": {
"msg": {
"$ref": "#/definitions/Binary"
},
"sender": {
"type": "string"
},
"token_id": {
"type": "string"
}
},
"definitions": {
"Binary": {
"description": "Binary is a wrapper around Vec<u8> to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec<u8>",
"type": "string"
}
}
}

View File

@ -1,31 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "NftInfoResponse",
"type": "object",
"properties": {
"extension": {
"description": "You can add any custom metadata here when you extend cw721-base",
"anyOf": [
{
"$ref": "#/definitions/Empty"
},
{
"type": "null"
}
]
},
"token_uri": {
"description": "Universal resource identifier for this NFT Should point to a JSON file that conforms to the ERC721 Metadata JSON Schema",
"type": [
"string",
"null"
]
}
},
"definitions": {
"Empty": {
"description": "An empty struct that serves as a placeholder in different places, such as contracts that don't set a custom message.\n\nIt is designed to be expressable in correct JSON and JSON Schema but contains no meaningful data. Previously we used enums without cases, but those cannot represented as valid JSON Schema (https://github.com/CosmWasm/cosmwasm/issues/451)",
"type": "object"
}
}
}

View File

@ -1,15 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "NumTokensResponse",
"type": "object",
"required": [
"count"
],
"properties": {
"count": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
}
}

View File

@ -1,97 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "OperatorsResponse",
"type": "object",
"required": [
"operators"
],
"properties": {
"operators": {
"type": "array",
"items": {
"$ref": "#/definitions/Approval"
}
}
},
"definitions": {
"Approval": {
"type": "object",
"required": [
"expires",
"spender"
],
"properties": {
"expires": {
"description": "When the Approval expires (maybe Expiration::never)",
"allOf": [
{
"$ref": "#/definitions/Expiration"
}
]
},
"spender": {
"description": "Account that can transfer/send the token",
"type": "string"
}
}
},
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
"oneOf": [
{
"description": "AtHeight will expire when `env.block.height` >= height",
"type": "object",
"required": [
"at_height"
],
"properties": {
"at_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
{
"description": "AtTime will expire when `env.block.time` >= time",
"type": "object",
"required": [
"at_time"
],
"properties": {
"at_time": {
"$ref": "#/definitions/Timestamp"
}
},
"additionalProperties": false
},
{
"description": "Never will never expire. Used to express the empty variant",
"type": "object",
"required": [
"never"
],
"properties": {
"never": {
"type": "object"
}
},
"additionalProperties": false
}
]
},
"Timestamp": {
"description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```",
"allOf": [
{
"$ref": "#/definitions/Uint64"
}
]
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
}
}
}

View File

@ -1,103 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "OwnerOfResponse",
"type": "object",
"required": [
"approvals",
"owner"
],
"properties": {
"approvals": {
"description": "If set this address is approved to transfer/send the token as well",
"type": "array",
"items": {
"$ref": "#/definitions/Approval"
}
},
"owner": {
"description": "Owner of the token",
"type": "string"
}
},
"definitions": {
"Approval": {
"type": "object",
"required": [
"expires",
"spender"
],
"properties": {
"expires": {
"description": "When the Approval expires (maybe Expiration::never)",
"allOf": [
{
"$ref": "#/definitions/Expiration"
}
]
},
"spender": {
"description": "Account that can transfer/send the token",
"type": "string"
}
}
},
"Expiration": {
"description": "Expiration represents a point in time when some event happens. It can compare with a BlockInfo and will return is_expired() == true once the condition is hit (and for every block in the future)",
"oneOf": [
{
"description": "AtHeight will expire when `env.block.height` >= height",
"type": "object",
"required": [
"at_height"
],
"properties": {
"at_height": {
"type": "integer",
"format": "uint64",
"minimum": 0.0
}
},
"additionalProperties": false
},
{
"description": "AtTime will expire when `env.block.time` >= time",
"type": "object",
"required": [
"at_time"
],
"properties": {
"at_time": {
"$ref": "#/definitions/Timestamp"
}
},
"additionalProperties": false
},
{
"description": "Never will never expire. Used to express the empty variant",
"type": "object",
"required": [
"never"
],
"properties": {
"never": {
"type": "object"
}
},
"additionalProperties": false
}
]
},
"Timestamp": {
"description": "A point in time in nanosecond precision.\n\nThis type can represent times from 1970-01-01T00:00:00Z to 2554-07-21T23:34:33Z.\n\n## Examples\n\n``` # use cosmwasm_std::Timestamp; let ts = Timestamp::from_nanos(1_000_000_202); assert_eq!(ts.nanos(), 1_000_000_202); assert_eq!(ts.seconds(), 1); assert_eq!(ts.subsec_nanos(), 202);\n\nlet ts = ts.plus_seconds(2); assert_eq!(ts.nanos(), 3_000_000_202); assert_eq!(ts.seconds(), 3); assert_eq!(ts.subsec_nanos(), 202); ```",
"allOf": [
{
"$ref": "#/definitions/Uint64"
}
]
},
"Uint64": {
"description": "A thin wrapper around u64 that is using strings for JSON encoding/decoding, such that the full u64 range can be used for clients that convert JSON numbers to floats, like JavaScript and jq.\n\n# Examples\n\nUse `from` to create instances of this and `u64` to get the value out:\n\n``` # use cosmwasm_std::Uint64; let a = Uint64::from(42u64); assert_eq!(a.u64(), 42);\n\nlet b = Uint64::from(70u32); assert_eq!(b.u64(), 70); ```",
"type": "string"
}
}
}

View File

@ -1,17 +0,0 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "TokensResponse",
"type": "object",
"required": [
"tokens"
],
"properties": {
"tokens": {
"description": "Contains all token_ids in lexicographical ordering If there are more than `limit`, use `start_from` in future queries to achieve pagination.",
"type": "array",
"items": {
"type": "string"
}
}
}
}

View File

@ -1,15 +0,0 @@
mod msg;
mod query;
mod receiver;
mod traits;
pub use cw0::Expiration;
pub use crate::msg::Cw721ExecuteMsg;
pub use crate::query::{
AllNftInfoResponse, Approval, ApprovalResponse, ApprovalsResponse, ContractInfoResponse,
Cw721QueryMsg, NftInfoResponse, NumTokensResponse, OperatorsResponse, OwnerOfResponse,
TokensResponse,
};
pub use crate::receiver::Cw721ReceiveMsg;
pub use crate::traits::{CustomMsg, Cw721, Cw721Execute, Cw721Query};

View File

@ -1,36 +0,0 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cosmwasm_std::Binary;
use cw0::Expiration;
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Cw721ExecuteMsg {
/// Transfer is a base message to move a token to another account without triggering actions
TransferNft { recipient: String, token_id: String },
/// Send is a base message to transfer a token to a contract and trigger an action
/// on the receiving contract.
SendNft {
contract: String,
token_id: String,
msg: Binary,
},
/// Allows operator to transfer / send the token from the owner's account.
/// If expiration is set, then this allowance has a time/height limit
Approve {
spender: String,
token_id: String,
expires: Option<Expiration>,
},
/// Remove previously granted Approval
Revoke { spender: String, token_id: String },
/// Allows operator to transfer / send any token from the owner's account.
/// If expiration is set, then this allowance has a time/height limit
ApproveAll {
operator: String,
expires: Option<Expiration>,
},
/// Remove previously granted ApproveAll permission
RevokeAll { operator: String },
}

View File

@ -1,132 +0,0 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cw0::Expiration;
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Cw721QueryMsg {
/// Return the owner of the given token, error if token does not exist
/// Return type: OwnerOfResponse
OwnerOf {
token_id: String,
/// unset or false will filter out expired approvals, you must set to true to see them
include_expired: Option<bool>,
},
/// Return operator that can access all of the owner's tokens.
/// Return type: `ApprovedResponse`
Approved { owner: String, operator: String },
/// List all operators that can access all of the owner's tokens.
/// Return type: `ApprovedForAllResponse`
ApprovedForAll {
owner: String,
/// unset or false will filter out expired approvals, you must set to true to see them
include_expired: Option<bool>,
start_after: Option<String>,
limit: Option<u32>,
},
/// Total number of tokens issued
NumTokens {},
/// With MetaData Extension.
/// Returns top-level metadata about the contract: `ContractInfoResponse`
ContractInfo {},
/// With MetaData Extension.
/// Returns metadata about one particular token, based on *ERC721 Metadata JSON Schema*
/// but directly from the contract: `NftInfoResponse`
NftInfo { token_id: String },
/// With MetaData Extension.
/// Returns the result of both `NftInfo` and `OwnerOf` as one query as an optimization
/// for clients: `AllNftInfo`
AllNftInfo {
token_id: String,
/// unset or false will filter out expired approvals, you must set to true to see them
include_expired: Option<bool>,
},
/// With Enumerable extension.
/// Returns all tokens owned by the given address, [] if unset.
/// Return type: TokensResponse.
Tokens {
owner: String,
start_after: Option<String>,
limit: Option<u32>,
},
/// With Enumerable extension.
/// Requires pagination. Lists all token_ids controlled by the contract.
/// Return type: TokensResponse.
AllTokens {
start_after: Option<String>,
limit: Option<u32>,
},
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct OwnerOfResponse {
/// Owner of the token
pub owner: String,
/// If set this address is approved to transfer/send the token as well
pub approvals: Vec<Approval>,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct Approval {
/// Account that can transfer/send the token
pub spender: String,
/// When the Approval expires (maybe Expiration::never)
pub expires: Expiration,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct ApprovalResponse {
pub approval: Approval,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct ApprovalsResponse {
pub approvals: Vec<Approval>,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct OperatorsResponse {
pub operators: Vec<Approval>,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct NumTokensResponse {
pub count: u64,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct ContractInfoResponse {
pub name: String,
pub symbol: String,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct NftInfoResponse<T> {
/// Universal resource identifier for this NFT
/// Should point to a JSON file that conforms to the ERC721
/// Metadata JSON Schema
pub token_uri: Option<String>,
/// You can add any custom metadata here when you extend cw721-base
pub extension: T,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct AllNftInfoResponse<T> {
/// Who can transfer the token
pub access: OwnerOfResponse,
/// Data on the token itself,
pub info: NftInfoResponse<T>,
}
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
pub struct TokensResponse {
/// Contains all token_ids in lexicographical ordering
/// If there are more than `limit`, use `start_from` in future queries
/// to achieve pagination.
pub tokens: Vec<String>,
}

View File

@ -1,43 +0,0 @@
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use cosmwasm_std::{to_binary, Binary, CosmosMsg, StdResult, WasmMsg};
/// Cw721ReceiveMsg should be de/serialized under `Receive()` variant in a ExecuteMsg
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub struct Cw721ReceiveMsg {
pub sender: String,
pub token_id: String,
pub msg: Binary,
}
impl Cw721ReceiveMsg {
/// serializes the message
pub fn into_binary(self) -> StdResult<Binary> {
let msg = ReceiverExecuteMsg::ReceiveNft(self);
to_binary(&msg)
}
/// creates a cosmos_msg sending this struct to the named contract
pub fn into_cosmos_msg<T: Into<String>, C>(self, contract_addr: T) -> StdResult<CosmosMsg<C>>
where
C: Clone + std::fmt::Debug + PartialEq + JsonSchema,
{
let msg = self.into_binary()?;
let execute = WasmMsg::Execute {
contract_addr: contract_addr.into(),
msg,
funds: vec![],
};
Ok(execute.into())
}
}
/// This is just a helper to properly serialize the above message.
/// The actual receiver should include this variant in the larger ExecuteMsg enum
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
enum ReceiverExecuteMsg {
ReceiveNft(Cw721ReceiveMsg),
}

View File

@ -1,166 +0,0 @@
use schemars::JsonSchema;
use serde::de::DeserializeOwned;
use serde::Serialize;
use crate::query::ApprovalResponse;
use crate::{
AllNftInfoResponse, ApprovalsResponse, ContractInfoResponse, NftInfoResponse,
NumTokensResponse, OperatorsResponse, OwnerOfResponse, TokensResponse,
};
use cosmwasm_std::{Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, StdResult};
use cw0::Expiration;
// TODO: move this somewhere else... ideally cosmwasm-std
pub trait CustomMsg: Clone + std::fmt::Debug + PartialEq + JsonSchema {}
impl CustomMsg for Empty {}
pub trait Cw721<T, C>: Cw721Execute<T, C> + Cw721Query<T>
where
T: Serialize + DeserializeOwned + Clone,
C: CustomMsg,
{
}
pub trait Cw721Execute<T, C>
where
T: Serialize + DeserializeOwned + Clone,
C: CustomMsg,
{
type Err: ToString;
fn transfer_nft(
&self,
deps: DepsMut,
env: Env,
info: MessageInfo,
recipient: String,
token_id: String,
) -> Result<Response<C>, Self::Err>;
fn send_nft(
&self,
deps: DepsMut,
env: Env,
info: MessageInfo,
contract: String,
token_id: String,
msg: Binary,
) -> Result<Response<C>, Self::Err>;
fn approve(
&self,
deps: DepsMut,
env: Env,
info: MessageInfo,
spender: String,
token_id: String,
expires: Option<Expiration>,
) -> Result<Response<C>, Self::Err>;
fn revoke(
&self,
deps: DepsMut,
env: Env,
info: MessageInfo,
spender: String,
token_id: String,
) -> Result<Response<C>, Self::Err>;
fn approve_all(
&self,
deps: DepsMut,
env: Env,
info: MessageInfo,
operator: String,
expires: Option<Expiration>,
) -> Result<Response<C>, Self::Err>;
fn revoke_all(
&self,
deps: DepsMut,
env: Env,
info: MessageInfo,
operator: String,
) -> Result<Response<C>, Self::Err>;
fn burn(
&self,
deps: DepsMut,
env: Env,
info: MessageInfo,
token_id: String,
) -> Result<Response<C>, Self::Err>;
}
pub trait Cw721Query<T>
where
T: Serialize + DeserializeOwned + Clone,
{
// TODO: use custom error?
// How to handle the two derived error types?
fn contract_info(&self, deps: Deps) -> StdResult<ContractInfoResponse>;
fn num_tokens(&self, deps: Deps) -> StdResult<NumTokensResponse>;
fn nft_info(&self, deps: Deps, token_id: String) -> StdResult<NftInfoResponse<T>>;
fn owner_of(
&self,
deps: Deps,
env: Env,
token_id: String,
include_expired: bool,
) -> StdResult<OwnerOfResponse>;
fn operators(
&self,
deps: Deps,
env: Env,
owner: String,
include_expired: bool,
start_after: Option<String>,
limit: Option<u32>,
) -> StdResult<OperatorsResponse>;
fn approval(
&self,
deps: Deps,
env: Env,
token_id: String,
spender: String,
include_expired: bool,
) -> StdResult<ApprovalResponse>;
fn approvals(
&self,
deps: Deps,
env: Env,
token_id: String,
include_expired: bool,
) -> StdResult<ApprovalsResponse>;
fn tokens(
&self,
deps: Deps,
owner: String,
start_after: Option<String>,
limit: Option<u32>,
) -> StdResult<TokensResponse>;
fn all_tokens(
&self,
deps: Deps,
start_after: Option<String>,
limit: Option<u32>,
) -> StdResult<TokensResponse>;
fn all_nft_info(
&self,
deps: Deps,
env: Env,
token_id: String,
include_expired: bool,
) -> StdResult<AllNftInfoResponse<T>>;
}

View File

@ -196,7 +196,7 @@ if (argv.instantiate) {
pyth_emitter_chain: pythChain,
});
console.log(`Deployed pyth contract at ${contractAddress}`);
console.log(`Deployed Pyth contract at ${contractAddress}`);
}
if (argv.migrate) {

View File

@ -1,162 +0,0 @@
import { LCDClient, MnemonicKey } from "@terra-money/terra.js";
import {
MsgInstantiateContract,
MsgStoreCode,
} from "@terra-money/terra.js";
import { readFileSync } from "fs";
import { Bech32, toHex } from "@cosmjs/encoding";
import { zeroPad } from "ethers/lib/utils.js";
import axios from "axios";
import yargs from "yargs";
import {hideBin} from "yargs/helpers";
export const TERRA_GAS_PRICES_URL = "https://fcd.terra.dev/v1/txs/gas_prices";
const argv = yargs(hideBin(process.argv))
.option('network', {
description: 'Which network to deploy to',
choices: ['mainnet', 'testnet', 'localterra'],
required: true
})
.option('artifact', {
description: 'Which WASM file to deploy',
type: 'string',
required: true
})
.option('mnemonic', {
description: 'Mnemonic (private key)',
type: 'string',
required: true
})
.help()
.alias('help', 'h').argv;
const artifact = argv.artifact;
/* Set up terra client & wallet */
const terra_host =
argv.network === "mainnet"
? {
URL: "https://lcd.terra.dev",
chainID: "columbus-5",
name: "mainnet",
}
: argv.network === "testnet"
? {
URL: "https://bombay-lcd.terra.dev",
chainID: "bombay-12",
name: "testnet",
}
: {
URL: "http://localhost:1317",
chainID: "columbus-5",
name: "localterra",
};
const lcd = new LCDClient(terra_host);
const feeDenoms = ["uluna"];
const gasPrices = await axios
.get(TERRA_GAS_PRICES_URL)
.then((result) => result.data);
const wallet = lcd.wallet(
new MnemonicKey({
mnemonic: argv.mnemonic
})
);
await wallet.sequence();
/* Deploy artifacts */
let codeId;
const contract_bytes = readFileSync(artifact);
console.log(`Storing WASM: ${artifact} (${contract_bytes.length} bytes)`);
const store_code = new MsgStoreCode(
wallet.key.accAddress,
contract_bytes.toString("base64")
);
const feeEstimate = await lcd.tx.estimateFee(
wallet.key.accAddress,
[store_code],
{
memo: "",
feeDenoms,
gasPrices,
}
);
console.log("Deploy fee: ", feeEstimate.amount.toString());
const tx = await wallet.createAndSignTx({
msgs: [store_code],
memo: "",
feeDenoms,
gasPrices,
fee: feeEstimate,
});
const rs = await lcd.tx.broadcast(tx);
const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1];
codeId = parseInt(ci);
console.log("Code ID: ", codeId);
/* Instantiate contracts.
*
* We instantiate the core contracts here (i.e. wormhole itself and the bridge contracts).
* The wrapped asset contracts don't need to be instantiated here, because those
* will be instantiated by the on-chain bridge contracts on demand.
* */
async function instantiate(codeId, inst_msg) {
var address;
await wallet
.createAndSignTx({
msgs: [
new MsgInstantiateContract(
wallet.key.accAddress,
wallet.key.accAddress,
codeId,
inst_msg
),
],
memo: "",
})
.then((tx) => lcd.tx.broadcast(tx))
.then((rs) => {
address = /"contract_address","value":"([^"]+)/gm.exec(rs.raw_log)[1];
});
console.log(`Instantiated ${contract} at ${address} (${convert_terra_address_to_hex(address)})`);
return address;
}
// example usage of instantiate:
// const contractAddress = await instantiate("wormhole.wasm", {
// gov_chain: govChain,
// gov_address: Buffer.from(govAddress, "hex").toString("base64"),
// guardian_set_expirity: 86400,
// initial_guardian_set: {
// addresses: [
// {
// bytes: Buffer.from(
// "beFA429d57cD18b7F8A4d91A2da9AB4AF05d0FBe",
// "hex"
// ).toString("base64"),
// },
// ],
// expiration_time: 0,
// },
// });
// Terra addresses are "human-readable", but for cross-chain registrations, we
// want the "canonical" version
function convert_terra_address_to_hex(human_addr) {
return "0x" + toHex(zeroPad(Bech32.decode(human_addr).data, 32));
}

View File

@ -1,217 +0,0 @@
import { Wallet, LCDClient, MnemonicKey } from "@terra-money/terra.js";
import {
StdFee,
MsgExecuteContract,
MsgInstantiateContract,
MsgMigrateContract,
MsgStoreCode,
MsgUpdateContractAdmin,
} from "@terra-money/terra.js";
import { readFileSync, readdirSync } from "fs";
async function main() {
const terra = new LCDClient({
URL: "http://localhost:1317",
chainID: "localterra",
});
const wallet = terra.wallet(
new MnemonicKey({
mnemonic:
"notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius",
})
);
const hardcodedGas = {
"wormhole.wasm": 5000000,
};
// Deploy Wormhole alone.
const file = "wormhole.wasm";
const contract_bytes = readFileSync(`../artifacts/${file}`);
console.log(`Storing WASM: ${file} (${contract_bytes.length} bytes)`);
// Get new code id.
const store_code = new MsgStoreCode(
wallet.key.accAddress,
contract_bytes.toString("base64")
);
const codeIds = {};
try {
const tx = await wallet.createAndSignTx({
msgs: [store_code],
memo: "",
fee: new StdFee(hardcodedGas["wormhole.wasm"], {
uluna: "100000",
}),
});
const rs = await terra.tx.broadcast(tx);
const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1];
codeIds[file] = parseInt(ci);
} catch (e) {
console.log("Failed to Execute");
}
// Perform a Centralised update.
await wallet
.createAndSignTx({
msgs: [
new MsgMigrateContract(
wallet.key.accAddress,
"terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au",
codeIds["wormhole.wasm"],
{
"action": ""
},
{ uluna: 1000 }
),
],
memo: "",
})
.then((tx) => terra.tx.broadcast(tx))
.then((rs) => console.log(rs));
await wallet
.createAndSignTx({
msgs: [
new MsgMigrateContract(
wallet.key.accAddress,
"terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6",
codeIds["token_bridge.wasm"],
{
"action": ""
},
{ uluna: 1000 }
),
],
memo: "",
})
.then((tx) => terra.tx.broadcast(tx))
.then((rs) => console.log(rs));
// Set the Admin to the contract.
await wallet
.createAndSignTx({
msgs: [
new MsgUpdateContractAdmin(
wallet.key.accAddress,
"terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au",
"terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au"
),
],
memo: "",
})
.then((tx) => terra.tx.broadcast(tx))
.then((rs) => console.log(rs));
// Deploy a new CodeID.
try {
const tx = await wallet.createAndSignTx({
msgs: [store_code],
memo: "",
fee: new StdFee(hardcodedGas["wormhole.wasm"], {
uluna: "100000",
}),
});
const rs = await terra.tx.broadcast(tx);
const ci = /"code_id","value":"([^"]+)/gm.exec(rs.raw_log)[1];
codeIds[file] = parseInt(ci);
} catch (e) {
console.log("Failed to Execute");
}
// Perform a Guardian Set Upgrade to check the following
// flow with six guardians rather than the default one.
const guardianUpgradeVAA = '01000000000100f8547caf1d1263e6b4742aef05691a9e2a7aa082bb2f1deb3850e43b801a87044cf786924d8adff5553f31b41149f94a32b568321390450f12c31aa15c2f941101000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000227cc370000000000000000000000000000000000000000000000000000000000436f72650200000000000106befa429d57cd18b7f8a4d91a2da9ab4af05d0fbe4ba0c2db9a26208b3bb1a50b01b16941c10d76db4ba0c2db9a26208b3bb1a50b01b16941c10d76db4ba0c2db9a26208b3bb1a50b01b16941c10d76db4ba0c2db9a26208b3bb1a50b01b16941c10d76db4ba0c2db9a26208b3bb1a50b01b16941c10d76db';
await wallet
.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
"terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au",
{
submit_v_a_a: {
vaa: Buffer.from(guardianUpgradeVAA, "hex").toString(
"base64"
),
},
},
{ uluna: 1000 }
),
],
memo: "",
})
.then((tx) => terra.tx.broadcast(tx))
.then((rs) => console.log(rs));
// Upgrace VAA with 5 signatures to test qurom threshold.
const upgradeVAA = '0100000001050058f5e6a55261e137b12405eb5acf3e4670101c3b7561c6694d7116b6afec85b153f90992fb5e0d6d5a79506f524324fb21894ef655367cc37a572b07a9bfe43301011dba8dca119605dcd30efaf7c4f6980afdf5d58f9625648b652288505abe19be11eabe7424e69d3dae682a84c58208237a975c5ed7757613f546763e14db621200021dba8dca119605dcd30efaf7c4f6980afdf5d58f9625648b652288505abe19be11eabe7424e69d3dae682a84c58208237a975c5ed7757613f546763e14db621200031dba8dca119605dcd30efaf7c4f6980afdf5d58f9625648b652288505abe19be11eabe7424e69d3dae682a84c58208237a975c5ed7757613f546763e14db621200041dba8dca119605dcd30efaf7c4f6980afdf5d58f9625648b652288505abe19be11eabe7424e69d3dae682a84c58208237a975c5ed7757613f546763e14db6212000000000100000001000100000000000000000000000000000000000000000000000000000000000000040000000000a653200000000000000000000000000000000000000000000000000000000000436f72650100030000000000000000000000000000000000000000000000000000000000000005';
// Perform a decentralised update with a signed VAA.
await wallet
.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
"terra14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9ssrc8au",
{
submit_v_a_a: {
vaa: Buffer.from(upgradeVAA, "hex").toString(
"base64"
),
},
},
{ uluna: 1000 }
),
],
memo: "",
})
.then((tx) => terra.tx.broadcast(tx))
.then((rs) => console.log(rs));
// Set the Admin of the Token Bridge to itself.
await wallet
.createAndSignTx({
msgs: [
new MsgUpdateContractAdmin(
wallet.key.accAddress,
"terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6",
"terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6"
),
],
memo: "",
})
.then((tx) => terra.tx.broadcast(tx))
.then((rs) => console.log(rs));
// Upgrade VAA for the Token Bridge.
const upgradeTokenVAA = '01000000010500088c284fe2adf0976511290902cbb1dd29239dcd9cb343936c8e76825777db0912eecb7d1be70ddc8b15091834bc0626ea52cc82a202c71f1dc2ff6acffa111b0101b9c36107b2fa1ad413ec6a71aca58d4cd44dea28b692c242805ff0c6df7ce0cb5648f92f5a17a1e1cd2e6df89abb236716d9556a03e6ec5d2ad463cd326d1b830102b9c36107b2fa1ad413ec6a71aca58d4cd44dea28b692c242805ff0c6df7ce0cb5648f92f5a17a1e1cd2e6df89abb236716d9556a03e6ec5d2ad463cd326d1b830103b9c36107b2fa1ad413ec6a71aca58d4cd44dea28b692c242805ff0c6df7ce0cb5648f92f5a17a1e1cd2e6df89abb236716d9556a03e6ec5d2ad463cd326d1b830104b9c36107b2fa1ad413ec6a71aca58d4cd44dea28b692c242805ff0c6df7ce0cb5648f92f5a17a1e1cd2e6df89abb236716d9556a03e6ec5d2ad463cd326d1b8301000000010000000100010000000000000000000000000000000000000000000000000000000000000004000000000441f94100000000000000000000000000000000000000000000546f6b656e4272696467650200030000000000000000000000000000000000000000000000000000000000000005';
// Perform a decentralised update with a signed VAA.
await wallet
.createAndSignTx({
msgs: [
new MsgExecuteContract(
wallet.key.accAddress,
"terra1nc5tatafv6eyq7llkr2gv50ff9e22mnf70qgjlv737ktmt4eswrquka9l6",
{
submit_vaa: {
data: Buffer.from(upgradeTokenVAA, "hex").toString(
"base64"
),
},
},
{ uluna: 1000 }
),
],
memo: "",
})
.then((tx) => terra.tx.broadcast(tx))
.then((rs) => console.log(rs));
}
main();

View File

@ -1,73 +0,0 @@
import { LCDClient, MnemonicKey } from "@terra-money/terra.js";
import {
MsgMigrateContract,
} from "@terra-money/terra.js";
import axios from "axios";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
export const TERRA_GAS_PRICES_URL = "https://fcd.terra.dev/v1/txs/gas_prices";
const argv = yargs(hideBin(process.argv))
.option('code_id', {
description: 'Which code id to upgrade to',
type: 'number',
})
.option('mnemonic', {
description: 'Mnemonic (private key)',
type: 'string',
required: true
})
.option('contract', {
description: 'Contract to upgrade',
type: 'string',
required: true
})
.help()
.alias('help', 'h').argv;
/* Set up terra client & wallet */
const terra_host = {
URL: "https://bombay-lcd.terra.dev",
chainID: "bombay-12",
name: "testnet",
};
const lcd = new LCDClient(terra_host);
const feeDenoms = ["uluna"];
const gasPrices = await axios
.get(TERRA_GAS_PRICES_URL)
.then((result) => result.data);
const wallet = lcd.wallet(
new MnemonicKey({
mnemonic: argv.mnemonic
})
);
await wallet.sequence();
/* Do upgrade */
const tx = await wallet.createAndSignTx({
msgs: [
new MsgMigrateContract(
wallet.key.accAddress,
argv.contract,
argv.code_id,
{
"action": ""
},
{ uluna: 1000 }
),
],
memo: "",
feeDenoms,
gasPrices,
});
const rs = await lcd.tx.broadcast(tx);
console.log(rs);

View File

@ -1 +0,0 @@
terra_sdk==0.14.0