wormhole/examples/messenger/terra/src/lib.rs

204 lines
6.8 KiB
Rust

use borsh::{
BorshDeserialize,
BorshSerialize,
};
use cosmwasm_std::{
entry_point,
DepsMut,
Env,
MessageInfo,
Response,
StdError,
StdResult,
};
use wormhole_sdk::{
parse_vaa,
post_message,
};
use messenger_common::Message;
mod messages;
use messages::*;
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
_deps: DepsMut,
_env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> StdResult<Response> {
Ok(Response::default().add_attribute("version", msg.version))
}
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(deps: DepsMut, env: Env, info: MessageInfo, msg: ExecuteMsg) -> StdResult<Response> {
match msg {
// Emit a new message targetting an address on a foreign chain. The message is emitted via
// Wormhole and routed by the Guardians to the destination contract.
ExecuteMsg::SendMessage { nonce, nick, text } => Ok(Response::default()
.add_attribute("action", "send_message")
.add_message(post_message(
nonce,
&Message { nick, text }
.try_to_vec()
.map_err(|_| StdError::generic_err("Encoding Failed"))?,
)?)),
// Receive a VAA containing a message from another chain. The message is stored in the
// Terra contract state and can be read out via QueryMsg.
ExecuteMsg::RecvMessage { vaa } => {
// Parse VAA and decode Payload into message.
let vaa = parse_vaa(deps, env, &vaa)?;
let msg = Message::try_from_slice(&vaa.payload)
.map_err(|_| StdError::generic_err("Invalid Message"))?;
Ok(Response::default()
.add_attribute("action", "receive_message")
.add_attribute("nick", msg.nick)
.add_attribute("text", msg.text))
}
}
}
#[cfg(test)]
mod testing {
use cosmwasm_std::testing::{
mock_dependencies,
mock_env,
mock_info,
};
use cosmwasm_std::{
Attribute,
Binary,
CosmosMsg,
SubMsg,
WasmMsg,
};
use messenger_common::Message;
use super::{
execute,
instantiate,
ExecuteMsg,
InstantiateMsg,
};
#[test]
fn test_send_message() {
// Test Messages
let instantiate_msg = InstantiateMsg {
version: "1.0.0".to_string(),
};
let send_msg = ExecuteMsg::SendMessage {
nonce: 0,
nick: "Bob".to_string(),
text: "Hello Alice".to_string(),
};
// Instantiate Contract
let mut deps = mock_dependencies(&[]);
let env = mock_env();
let info = mock_info("addr0000", &[]);
instantiate(deps.as_mut(), env, info, instantiate_msg).unwrap();
// Send a Message
let info = mock_info("addr0000", &[]);
let result = execute(deps.as_mut(), mock_env(), info, send_msg).unwrap();
// Contract should have emitted a Msg targetting the wormhole contract.
assert_eq!(
result.messages,
vec![SubMsg::new(CosmosMsg::Wasm(WasmMsg::Execute {
contract_addr: wormhole_sdk::id().to_string(),
funds: vec![],
msg: Binary::from(&[
123, 34, 112, 111, 115, 116, 95, 109, 101, 115, 115, 97, 103, 101, 34, 58, 123,
34, 109, 101, 115, 115, 97, 103, 101, 34, 58, 34, 65, 119, 65, 65, 65, 69,
74, 118, 89, 103, 115, 65, 65, 65, 66, 73, 90, 87, 120, 115, 98, 121, 66, 66, 98,
71, 108, 106, 90, 81, 61, 61, 34, 44, 34, 110, 111, 110, 99, 101, 34, 58, 48, 125, 125
]),
}))]
);
}
/// This test currently would fail until cosmwasm can mock cross contract calls, but is here for
/// documentation and future inclusion, see MockQuerier for details:
/// https://github.com/CosmWasm/cosmwasm/blob/0.16/packages/std/src/mock.rs#L389
fn test_recv_message() {
// Test Messages
let instantiate_msg = InstantiateMsg {
version: "1.0.0".to_string(),
};
// Submit a pre-encoded Message VAA.
let recv_msg = ExecuteMsg::RecvMessage {
vaa: Binary::from(&[
0x01, // Version
0x00, 0x00, 0x00, 0x00, // Guardian Set Index
0x01, // Guardian Signature Len
0x00, // Guardian 0.
0xb0, // Recovery 0.
// Signature 0
0x72, 0x50, 0x5b, 0x5b, 0x99, 0x9c, 0x1d, 0x08, 0x90, 0x5c, 0x02, 0xe2, 0xb6, 0xb2,
0x83, 0x2e, 0xf7, 0x2c, 0x0b, 0xa6, 0xc8, 0xdb, 0x4f, 0x77, 0xfe, 0x45, 0x7e, 0xf2,
0xb3, 0xd0, 0x53, 0x41, 0x0b, 0x1e, 0x92, 0xa9, 0x19, 0x4d, 0x92, 0x10, 0xdf, 0x24,
0xd9, 0x87, 0xac, 0x83, 0xd7, 0xb6, 0xf0, 0xc2, 0x1c, 0xe9, 0x0f, 0x8b, 0xc1, 0x86,
0x9d, 0xe0, 0x89, 0x8b, 0xda, 0x7e, 0x98, 0x01, 0x00, 0x00, 0x00,
0x01, // Timestamp
0x00, 0x00, 0x00, 0x01, // Nonce
0x00, 0x01, // Chain Solana
// Emitter Solana
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x3c, 0x1b,
0xfa, // Sequence
0x00, // Consistency
// Payload
5, 0, 0, 0, 65, 108, 105, 99, 101, 9, 0, 0, 0, 72, 101, 108, 108, 111, 32, 66, 111,
98,
]),
};
use borsh::BorshSerialize;
println!(
"{:?}",
Message {
nick: "Alice".to_string(),
text: "Hello Bob".to_string(),
}
.try_to_vec()
);
// Instantiate Contract
let mut deps = mock_dependencies(&[]);
let env = mock_env();
let info = mock_info("addr0000", &[]);
instantiate(deps.as_mut(), env, info, instantiate_msg).unwrap();
// Receive a Message
let info = mock_info("addr0000", &[]);
let result = execute(deps.as_mut(), mock_env(), info, recv_msg).unwrap();
assert_eq!(
result.attributes,
vec![
Attribute {
key: "action".to_string(),
value: "receive_message".to_string(),
},
Attribute {
key: "nick".to_string(),
value: "Alice".to_string(),
},
Attribute {
key: "text".to_string(),
value: "Hello Bob".to_string(),
}
]
);
}
}