Skip to content

Commit

Permalink
Add developer docs for connecting apps (#3603)
Browse files Browse the repository at this point in the history
- [X] ucs03 Asset Transfer - CosmWasm
- [x] ucs03 Asset Transfer - Solidity

- ~~ucs03 Data Transfer - CosmWasm~~ (#3622)
- ~~ucs03 Data Transfer - Solidity~~ (#3622)
- ~~Connecting New Chains~~ (#3465)
  • Loading branch information
cor authored Jan 26, 2025
2 parents 3370db7 + 3c4d31f commit 446ba60
Show file tree
Hide file tree
Showing 7 changed files with 477 additions and 29 deletions.
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

0 comments on commit 446ba60

Please sign in to comment.