How to get the AccountId of the contract instantiated in the contract in Substrate ink - substrate

I want to instantiate another contract inside a contract and get the AccountId of that contract.
Can anyone tell me how to do that?
Instantiate SampleContract2 in the add_contract function of SampleContract1.
I want to get the AccountId of the instantiated SampleContract2, manage it in a list, and use the AccountId later to be able to access SmapleContract2.
In the future, I would like to increase the types of contracts, so I would like to use AccountId, which can be used for general purposes, instead of the SmapleContract2 type for the list.
Why does "sample_contract_2.env().account_id()" return the address of SampleContract1?
-- snip --
#[ink(storage)]
pub struct SampleContract1 {
next_id:u128,
account_id_list:Mapping<u128, AccountId>
}
-- snip --
impl SampleContract1 {
#[ink(constructor)]
pub fn new() -> Self {
Self {
account_id_list: Mapping::default(),
next_id:0,
}
}
#[ink(message)]
pub fn add_contract(&mut self ) -> Result<()> {
let sample_contract_2 = SampleContract2::new();
let contract_address = sample_contract_2.env().account_id(); <- ###### Address of SampleContract1 is obtained.
self.token_list.insert(&self.next_id, &contract_address );
self.next_id = self.next_id + 1;
Ok(())
}
Thank you.

Related

How can I use the same default implementation for this Rust trait

I want to implement a trait that allows assigning generic types. So far I have tested this for u32 and String types:
trait Test {
fn test(&self, input: &str) -> Self;
}
impl Test for String {
fn test(&self, input: &str) -> Self {
input.parse().unwrap()
}
}
impl Test for u32 {
fn test(&self, input: &str) -> Self {
input.parse().unwrap()
}
}
fn main() {
let mut var = 0u32;
let mut st = String::default();
var = var.test("12345678");
st = st.test("Text");
println!("{}, {}", var, st);
}
I know this code is not perfect, and I should be using a Result return instead of unwrapping, but please set this aside as this is a quick example. The implementations for u32 and String are exactly the same, so I would like to use a default implementation for both instead of copying & pasting the code. I have tried using one, but as the returned type Self differs in both, compiler cannot determine the type size and errors.
How could I write a default implementation in this case?
Default implementation
The following bounds on Self are required for the default implementation:
Self: Sized because Self is returned from the function and will be placed in the caller's stack
Self: FromStr because you're calling parse() on input and expecting it to produce a value of type Self
<Self as FromStr>::Err: Debug because when you unwrap a potential error and the program panics Rust wants to be able to print the error message, which requires the error type to implement Debug
Full implementation:
use std::fmt::Debug;
use std::str::FromStr;
trait Test {
fn test(&self, input: &str) -> Self
where
Self: Sized + FromStr,
<Self as FromStr>::Err: Debug,
{
input.parse().unwrap()
}
}
impl Test for String {}
impl Test for u32 {}
fn main() {
let mut var = 0u32;
let mut st = String::default();
var = var.test("12345678");
st = st.test("Text");
println!("{}, {}", var, st);
}
playground
Generic implementation
A generic blanket implementation is also possible, where you automatically provide an implementation of Test for all types which satisfy the trait bounds:
use std::fmt::Debug;
use std::str::FromStr;
trait Test {
fn test(&self, input: &str) -> Self;
}
impl<T> Test for T
where
T: Sized + FromStr,
<T as FromStr>::Err: Debug,
{
fn test(&self, input: &str) -> Self {
input.parse().unwrap()
}
}
fn main() {
let mut var = 0u32;
let mut st = String::default();
var = var.test("12345678");
st = st.test("Text");
println!("{}, {}", var, st);
}
playground
Macro implementation
This implementation, similar to the default implementation, allows you to pick which types get the implementation, but it's also similar to the generic implementation, in that it doesn't require you to modify the trait method signature with any additional trait bounds:
trait Test {
fn test(&self, input: &str) -> Self;
}
macro_rules! impl_Test_for {
($t:ty) => {
impl Test for $t {
fn test(&self, input: &str) -> Self {
input.parse().unwrap()
}
}
}
}
impl_Test_for!(u32);
impl_Test_for!(String);
fn main() {
let mut var = 0u32;
let mut st = String::default();
var = var.test("12345678");
st = st.test("Text");
println!("{}, {}", var, st);
}
playground
Key differences
The key differences between the 3 approaches:
The default implementation makes the trait bounds inherent to the method's signature, so all types which impl Test must be sized, and have a FromStr impl with a debuggable error type.
The default implementation allows you to selectively pick which types get Test implementations.
The generic implementation doesn't add any trait bounds to the trait method's signature so a greater variety of types could potentially implement the trait.
The generic implementation automatically implements the trait for all types which satisfy the bounds, you cannot selectively "opt out" of the generic implementation if there are some types which you'd prefer not to implement the trait.
The macro implementation does not require modifying the trait method signature with additional trait bounds and allows you to selectively pick which types get the implementation.
The macro implementation is a macro and suffers all the downsides of being a macro: harder to read, write, maintain, increases compile times, and macros are essentially opaque to static code analyzers which makes it harder to easily type-check your code.

Send messages to clients with multiple references to websockets

My question here is in the context of using actix-web with Rust.
Unfortunately I can't explain this without a somewhat hefty code example, so let me start with that.
struct MyWs {
game: Arc<RwLock<Game>>,
}
impl Actor for MyWs {
type Context = ws::WebsocketContext<Self>;
}
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWs {
fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
match msg {
Ok(ws::Message::Text(text)) => {
debug!("Echoing text with {:?}", text);
self.game.write().unwrap().some_method();
ctx.text(text)
},
_ => (),
}
}
}
struct Game {
websockets: Vec<Arc<RwLock<MyWs>>>,
}
impl Game {
pub fn new() -> GameWrapper {
GameWrapper {
websockets: vec![],
}
}
pub fn add_websocket(&mut self, my_ws: Arc<RwLock<MyWs>>) {
self.websockets.push(my_ws);
}
pub fn some_method(&mut self) {
// Do something to influence internal state.
self.push_state();
}
pub fn push_state(&self) {
for w in self.websockets {
// I'm not sure about this part, idk how to access the
// WebsocketContext with which I can send stuff back to the client.
let game_state = get_game_state_or_something();
w.write().unwrap().ctx.text(self.game_state);
}
}
}
struct GameWrapper {
pub game: Arc<RwLock<Game>>,
}
impl GameWrapper {
pub fn new(game: Arc<RwLock<Game>>) -> GameWrapper {
GameWrapper { game }
}
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
let game = Arc::new(RwLock::new(Game::new()));
let game_wrapper = RwLock::new(GameWrapper::new(game.clone()));
let game_wrapper_data = web::Data::new(game_wrapper);
HttpServer::new(move || {
App::new()
.app_data(game_wrapper_data.clone())
.route("/play_game", web::get().to(play_game))
})
.bind(ip_port)?
.run()
.await
}
pub async fn play_game(
req: HttpRequest,
stream: web::Payload,
game_wrapper: web::Data<GameWrapper>,
) -> impl Responder {
let my_ws = MyWs { game: game_wrapper.game.clone() };
let my_ws = Arc::new(RwLock::new(my_ws));
let mut game = game_wrapper.game.write().unwrap();
game.add_websocket(my_ws);
let resp = ws::start(my_ws, &req, stream); // This is the problem.
let resp = match resp {
Ok(resp) => resp,
Err(e) => return HttpResponse::from_error(e),
};
debug!("Successfully upgraded to websocket");
resp
}
Let me explain what I'm trying to do first. When I client connects, I establish a websocket with them. I need a list of these websockets, so when something changes in Game, I can push an update to all clients.
I bind the play_game function as the handler for the play_game route. In this function, I upgrade the HTTP get request to a websocket. IBefore that, I make a copy of an Arc+RwLock of a Game and pass it into MyWs, the websocket struct. You can see in the handle function of the MyWs impl of StreamHandler that I modify the Game (with the some_method function). This is fine so far.
Things explode when I try to get multiple references to the websocket. You can see in play_game that I call add_websocket, giving Game a reference to it, so it can push updates back to all clients when something changes. For example, after calling some_method, we would call push_updates. The problem with this, is ws::start doesn't take in an Arc, it must take in an Actor that impls StreamHandler with a WebSocketContext.
So my main two issues are:
I need a way to keep multiple references to the websocket, so I can talk to the client from multiple locations (read: threads).
I need some way to even do this. I'm not sure in actix how to actually send messages back to the client outside of the context of my MyWs actor. The framework passes in the WebSocketContext to handle, but I don't know how to get my hands on this myself.
My ideas for fixing this:
In the handle (or started) function of MyWs, pass out a reference to Context into self.game. This doesn't work because I'm moving out a mutable ref.
Make my own ws::start that can take a reference. I haven't tried this yet because it seems like I'd end up rewriting a lot.
Somehow impl Actor and StreamHandler on an Arc, or my own struct with interior mutability / something that allows me to keep multiple references to it.
This doesn't really help me send messages back because I still don't know how to send messages back via the websocket outside of the context of the handle function.
Sorry for the length of this question. The tl;dr is, how do I get multiple references to a websocket in actix-web and send messages to the client with them?
Here are the relevant docs for each of the components I'm using:
https://docs.rs/actix-web-actors/2.0.0/actix_web_actors/ws/fn.start.html
https://docs.rs/actix-web-actors/2.0.0/actix_web_actors/ws/struct.WebsocketContext.html
https://actix.rs/docs/websockets/
Okay so the solution to my dilemma here was unsurprisingly to change the way I was trying to solve this problem. Instead of holding multiple references to the websockets, what I really need is references to each of the actors that hold the websocket. I figure this is how you're meant to do it, given Actix is an actor framework.
This means the code should look like this:
impl Game {
...
pub fn register_actor(&mut self, actor: Addr<MyWs>) {
self.actors.push(actor);
}
}
pub async fn play_game(
req: HttpRequest,
stream: web::Payload,
game_wrapper: web::Data<GameWrapper>,
) -> impl Responder {
let my_ws = MyWs { game: game_wrapper.game.clone() };
let my_ws = Arc::new(RwLock::new(my_ws));
let mut game = game_wrapper.game.write().unwrap();
let res = ws::start_with_addr(my_ws, &req, stream);
let (addr, resp) = match res {
Ok(res) => res,
Err(e) => return HttpResponse::from_error(e),
};
game_manager.register_actor(handle, addr);
debug!("Successfully upgraded to websocket");
resp
}
You can then send messages to the actor instead via the Addr<MyWs>.
I'm going to leave the question for a while in case others have ideas for how to do this whole thing better.

Can we return an array of `AccountID` in NEAR?

Suppose I have a struct
pub struct Test {
pub participant: Set<AccountId>
}
And I created a new account and inserted to participant using the insert function, I can get len of participant using len() method.
How can I get the address?
pub fn get_address(&self) -> Vec<AccountId> {
self.participient.contains() // can't get data
}
You can do
self.participant.to_vec()

String attribute set in init method always returns empty string

I have the following struct with impl:
#[near_bindgen]
#[derive(Default, Serialize, Deserialize, BorshDeserialize, BorshSerialize, Debug)]
pub struct MyStruct {
owner: String
}
#[near_bindgen(init => new)]
impl MyStruct {
fn new() -> Self {
Self {
owner: "bob".to_string()
}
}
fn get_owner(&self) -> String {
return self.owner;
}
}
Then I deploy the contract using near deploy my_contract --masterAccount myAccount
If I call get_owner using near-shell: near call my_contract get_owner --accountId=myAccount It always returns "" instead of the expected "bob".
It seems like the new method might not get called on deployment.
Initializer doesn't automatically get called on deploy. deploy just deploys the code and doesn't call anything on the contract. We should probably add a new method to shell, that does deploy_and_call. But for now just call new manually.
The reason why we don't initialize automatically is that initializer might take additional arguments. You can pass an owner to new method. Here is an example how to use initializer with custom arguments and as well as how to make sure a contract can't be called without initialization:
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct FunToken {
/// AccountID -> Account details.
pub accounts: Map<AccountId, Account>,
/// Total supply of the all token.
pub total_supply: Balance,
}
impl Default for FunToken {
fn default() -> Self {
env::panic(b"Not initialized");
unreachable!();
}
}
#[near_bindgen(init => new)]
impl FunToken {
pub fn new(owner_id: AccountId, total_supply: Balance) -> Self {
let mut ft = Self { accounts: Map::new(b"a".to_vec()), total_supply };
let mut account = ft.get_account(&owner_id);
account.balance = total_supply;
ft.accounts.insert(&owner_id, &account);
ft
}
}
From here: https://github.com/nearprotocol/near-bindgen/blob/master/examples/fun-token/src/lib.rs#L52-L77
Basically it panics during Default call, so non initialized contract can't be called.
Initializer functions are usually used when you need to parametrize the initialization of the contract. If there are no parameters then just implement Default trait:
impl Default for MyStruct {
fn default() -> Self {
Self {
owner: "bob".to_string()
}
}}

Replace a struct member with a new value that uses the previous value

I have a struct which owns a boxed value of some trait type. The struct itself also implements the same trait. I would like to replace the value with a new instance of the same struct, which wraps it.
The following code, which does not compile, should make it more clear what I am trying to do:
trait T {}
struct S {
t: Box<dyn T>,
}
impl T for S {}
impl S {
fn new(t: Box<dyn T>) -> Self {
Self { t }
}
fn wrap_t(&mut self) {
self.t = Box::new(Self::new(self.t))
}
}
This fails:
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:14:37
|
14 | self.t = Box::new(Self::new(self.t))
| ^^^^ cannot move out of borrowed content
Implementing wrap_t like this does compile:
use std::mem;
fn wrap_t(&mut self) {
unsafe {
let old_t = mem::replace(&mut self.t, mem::uninitialized());
let new_t = Box::new(Self::new(old_t));
let uninit = mem::replace(&mut self.t, new_t);
mem::forget(uninit);
}
}
I wonder if there is a safe way to do this.
The only unsafe function you are using is mem::uninitialized. You need something to pass to mem::replace, but implementing Default won't work because default() returns Self, which prevents it from being object-safe. Similarly, you can't implement Clone to duplicate the old value, since clone() also returns Self.
You can just implement a dummy type for the purpose though:
struct Dummy;
impl T for Dummy {}
fn wrap_t(&mut self) {
let old_t = mem::replace(&mut self.t, Box::new(Dummy));
let new_t = Box::new(Self::new(old_t));
mem::replace(&mut self.t, new_t);
}
You also won't need the mem::forget here now either (I'm assuming that was there to prevent undefined behaviour when the uninitialised memory was dropped).
As an alternative to Clone, you can roll your own own, which clones to a Box<dyn T>, avoiding having a Self in the method signature, so the trait stays object safe:
trait T: Debug {
fn clone_in_box(&self) -> Box<dyn T>;
}
impl T for S {
fn clone_in_box(&self) -> Box<dyn T> {
Box::new(S {
t: self.t.clone_in_box(),
})
}
}
fn wrap_t(&mut self) {
let cloned = self.clone_in_box();
let old_t = mem::replace(&mut self.t, cloned);
let new_t = Box::new(Self::new(old_t));
mem::replace(&mut self.t, new_t);
}
There is also an alternative design, which is much simpler to understand when reading the code. That is just to consume self and return a new object:
fn wrap_t(self) -> Self {
Self::new(Box::new(Self::new(self.t)))
}
And instead of this:
s.wrap_t();
You would do:
s = s.wrap_t();

Resources