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

Add developer docs for connecting apps #3603

Merged
69 changes: 40 additions & 29 deletions docs/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,21 +147,6 @@ export default defineConfig({
label: "Introduction",
link: "/"
},
/*
{
label: "Connect",
items: [
{
label: "App",
link: "/connect/app"
},
{
label: "New Chain",
link: "/connect/new-chain"
}
]
},
*/
{
label: "Protocol",
items: [
Expand Down Expand Up @@ -195,6 +180,46 @@ export default defineConfig({
directory: "/architecture"
}
},
{
label: "Connect",
items: [
{
label: "Apps",
items: [
{
label: "Asset Transfer",
items: [
{
label: "Introduction",
link: "/connect/app/asset-transfer"
},
{
label: "Solidity",
link: "/connect/app/asset-transfer/solidity"
},
{
label: "CosmWasm",
link: "/connect/app/asset-transfer/cosmwasm"
}
]
}
// {
// label: "Custom Data",
// items: [
// {
// label: "Introduction",
// link: "/connect/app/custom-data"
// }
// ]
// }
]
}
// {
// label: "New Chain",
// link: "/connect/new-chain"
// }
]
},
{
label: "Concepts",
autogenerate: {
Expand Down Expand Up @@ -229,20 +254,6 @@ export default defineConfig({
link: "/integrations/typescript",
badge: { variant: "success", text: "new" }
},
{
label: "UCS01",
badge: { variant: "success", text: "new" },
items: [
{
label: "Solidity",
link: "/integrations/ucs01/solidity"
},
{
label: "CosmWasm",
link: "/integrations/ucs01/cosmwasm"
}
]
},
{
label: "API",
collapsed: true,
Expand Down
280 changes: 280 additions & 0 deletions docs/src/content/docs/connect/app/asset-transfer/cosmwasm.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
---
title: "ucs03-zkgm Asset Transfer Tutorial - CosmWasm"
description: "Transfer assets using Union's ucs03 protocol in a CosmWasm contract"
template: doc
---

import { Tabs, TabItem, FileTree, Steps, Badge } from '@astrojs/starlight/components'

# Prerequisites

This tutorial assumes that you have experience creating contracts in CosmWasm. If you need to familiarize yourself with CosmWasm, you should start with the [CosmWasm book](https://book.cosmwasm.com/) and the other [resources listed by the CosmWasm team](https://cosmwasm.com/build).

The Union team uses [Nix](https://nixos.org/) to manage developer environments. While this tutorial may mention different developer tools, it will not guide you through setting each one up.

This tutorial will assume that you have a working rust tool chain, including `cargo`.

You will also need a chain that supports CosmWasm running where you plan to deploy ucs03 and your app. This tutorial will assume you are deploying your contract on `union-testnet-9`.

Users will need to find a valid RPC node to use as `RPC_URL` throughout the tutorial.

# Tutorial

1. Write your contract
2. Deploy your contract
3. Example transfer

## Write Your Contract

To demonstrate asset transfers with ucs03, this tutorial will walk you through creating a simple contract that sends a single token.

### Project Bootstrapping

If you don't already have a project folder for your contract, make one now and navigate inside.

```sh
cargo new --lib example-ucs03-cosmwasm
cd example-ucs03-cosmwasm
```

Add required dependencies to the `Cargo.toml` file.

```toml title="Cargo.toml"
[package]
name = "example-ucs03-cosmwasm" # name of the project
version = "0.1.0"
edition = "2021"

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

[dependencies]
cosmwasm-schema = { version = "2.1.4" }
cosmwasm-std = { version = "2.1.4", default-features = false, features = ["std", "staking", "stargate"] }
serde = { version = "1.0.210", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.64", default-features = false }

[features]
library = []

[profile.release]
opt-level = "z"
strip = true
```

Below is a sample contract that can be pasted into `lib.rs`.

This contract exposes the transfer message from ucs03-zkgm (`Ucs03ExecuteMsg`), then sends that message to the deployed ucs03-zkgm. To see all the messages exposed by ucs03-zkgm, refer to the contract in our [repository](https://github.com/unionlabs/union/blob/49dfa17d04b52509e5122d13e79bfc4a65d4a811/cosmwasm/ibc-union/app/ucs03-zkgm/src/msg.rs#L16)

```rust title="src/lib.rs"
use cosmwasm_schema::cw_serde;
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
to_json_binary, Coin, DepsMut, Env, MessageInfo, Response, StdResult, Uint128, Uint256, WasmMsg,
};

#[cw_serde]
pub struct InstantiateMsg {}

#[derive(serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ExecuteMsg {
Transfer {
channel_id: u32,
receiver: String,
base_token: String,
base_amount: Uint128,
quote_token: String,
quote_amount: Uint256,
contract_address: String,
},
}

#[derive(serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Ucs03ExecuteMsg {
Transfer {
channel_id: u32,
receiver: String,
base_token: String,
base_amount: Uint128,
quote_token: String,
quote_amount: Uint256,
timeout_height: u64,
timeout_timestamp: u64,
salt: String,
},
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
_deps: DepsMut,
_env: Env,
_info: MessageInfo,
_msg: InstantiateMsg,
) -> StdResult<Response> {
Ok(Response::default())
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut,
env: Env,
_info: MessageInfo,
msg: ExecuteMsg,
) -> StdResult<Response> {
match msg {
ExecuteMsg::Transfer {
channel_id,
receiver,
base_token,
base_amount,
quote_token,
quote_amount,
contract_address,
} => transfer(
deps,
env,
channel_id,
receiver,
base_token,
base_amount,
quote_token,
quote_amount,
contract_address,
),
}
}

fn transfer(
_deps: DepsMut,
_env: Env,
channel_id: u32,
receiver: String,
base_token: String,
base_amount: Uint128,
quote_token: String,
quote_amount: Uint256,
contract_address: String,
) -> StdResult<Response> {
let msg = WasmMsg::Execute {
contract_addr: contract_address,
msg: to_json_binary(&Ucs03ExecuteMsg::Transfer {
channel_id,
receiver: receiver.clone(),
base_token: base_token.clone(),
base_amount,
quote_token,
quote_amount,
timeout_height: 1000000000000,
timeout_timestamp: 2737670312,
salt: "0x5dbda6be8b35e888c9d4e64c3ce080fbc735e8b907ca5a38222ac522d085ec2b".to_string(),
})
.expect("can convert into json binary"),
funds: vec![Coin {
denom: base_token,
amount: base_amount,
}],
};

Ok(Response::new()
.add_message(msg)
.add_attribute("action", "transfer")
.add_attribute("recipient", receiver)
.add_attribute("amount", base_amount.to_string()))
}
```
### Building the Contract

With this contract code ready, the WASM blob can be built.

```sh
RUSTFLAGS='-C target-cpu=mvp -C opt-level=z' cargo build \
--target wasm32-unknown-unknown \
--no-default-features \
--lib \
--release \
-Z build-std=std,panic_abort \
-Z build-std-features=panic_immediate_abort

mkdir -p build
```

The contract can now be deployed.

## Deploying your Contract

With the WASM blob ready, the contract can be deployed.

```sh
uniond tx wasm store ./build/contract.wasm \
--from $KEY_NAME \
--gas auto \
--gas-adjustment 1.4 \
--chain-id union-testnet-9 \
--node $RPC_URL \
--yes

TX_HASH=..
```

Be sure to copy the `CODE_ID` of the newly stored code. Using the previous transaction hash, you can see it by running this command:
```sh
uniond query tx $TX_HASH --node $RPC_URL | rg -C 1 "code_id"
```

Next, submit a transaction to instantiate the contract. Copy the value of the **NEW** transaction hash into a shell variable (`TX_HASH`).

```sh
uniond tx wasm instantiate $CODE_ID "{}" \
--node $RPC_URL \
--from $KEY_NAME \
--label $CONTRACT_NAME \
--no-admin \
--gas auto \
--gas-adjustment 1.4 \
--chain-id union-testnet-9

TX_HASH=..
```

You can then get the contract address by running:
```sh
uniond query tx $TX_HASH --node $RPC_URL | rg -C 1 "_contract_address"
```

## Example Transfer

With the address of your contract in hand, a sample transfer can now be conducted.

First, prepare a `payload.json` that will hold the main message of the transfer.

This will send UNO to a Holesky address of your choice

```json title="payload.json"
{
"transfer": {
"channel_id": 7,
"receiver": "<RECEIVER_ADDRESS_HEX_PREFIXED>",
"base_token": "muno",
"base_amount": 1000000,
"quote_token": "0xf2865969cf99a28bb77e25494fe12d5180fe0efd",
"quote_amount": "1000000",
"contract_address": "union19hspxmypfxsdsnxttma8rxvp7dtcmzhl9my0ee64avg358vlpawsdvucqa",
}
}
```

The message can then be sent to the contract for execution.

```sh
uniond \
tx wasm execute $CONTRACT_ADDRESS "$(jq -c '.' payload.json)" \
--from $KEY_NAME \
--gas auto \
--gas-adjustment 1.4 \
--chain-id union-testnet-9 \
--node $RPC_URL \
--amount 2000000muno
```
10 changes: 10 additions & 0 deletions docs/src/content/docs/connect/app/asset-transfer/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
title: "Asset Transfer Tutorial"
description: "Transfer assets using Union's ZKGM protocol"
template: doc
---

This tutorial will walk you through creating a smart contract to send assets with Union. Asset transfer can be achieved through the message passing exposed by ZKGM (aka ucs03-zkgm).

At this point, you can continue the tutorial with either our [CosmWasm](/connect/app/asset-transfer/cosmwasm) or [Solidity](/connect/app/asset-transfer/solidity) specific tutorials.

Loading
Loading