generated from multiversx/mx-template-sc
-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #104 from multiversx/paymaster-interactor
paymaster: Add interactor
- Loading branch information
Showing
11 changed files
with
337 additions
and
1 deletion.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Pem files are used for interactions, but shouldn't be committed | ||
*.pem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
[package] | ||
name = "rust-interact" | ||
version = "0.0.0" | ||
authors = ["you"] | ||
edition = "2021" | ||
publish = false | ||
|
||
[[bin]] | ||
name = "rust-interact" | ||
path = "src/interactor_main.rs" | ||
|
||
[dependencies.paymaster] | ||
path = ".." | ||
|
||
[dependencies.multiversx-sc-snippets] | ||
version = "0.52.3" | ||
|
||
[dependencies.multiversx-sc] | ||
version = "0.52.3" | ||
|
||
[dependencies] | ||
clap = { version = "4.4.7", features = ["derive"] } | ||
serde = { version = "1.0", features = ["derive"] } | ||
toml = "0.8.6" | ||
|
||
# [workspace] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
gateway = 'https://devnet-gateway.multiversx.com' | ||
|
||
relayer_addr = "erd19azy5vlq343un82cqz03744vmta9ya8l5xwj3ywz7r8m8pkttd0syhkffa" | ||
egld_mex_pair_address = "erd1qqqqqqqqqqqqqpgqzw0d0tj25qme9e4ukverjjjqle6xamay0n4s5r0v9g" | ||
egld_usdc_pair_address = "erd1qqqqqqqqqqqqqpgqtqfhy99su9xzjjrq59kpzpp25udtc9eq0n4sr90ax6" | ||
wegld_address = "erd1qqqqqqqqqqqqqpgqpv09kfzry5y4sj05udcngesat07umyj70n4sa2c0rp" | ||
router_address = "erd1qqqqqqqqqqqqqpgqa7hv0nahgsl8tz0psat46x0tchm0wuyc0n4s6q28ad" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
#![allow(non_snake_case)] | ||
|
||
mod paymaster_config; | ||
mod proxy; | ||
|
||
use multiversx_sc_snippets::imports::*; | ||
use multiversx_sc_snippets::sdk; | ||
use paymaster_config::Config; | ||
use serde::{Deserialize, Serialize}; | ||
use std::{ | ||
io::{Read, Write}, | ||
path::Path, | ||
}; | ||
|
||
const GATEWAY: &str = sdk::gateway::DEVNET_GATEWAY; | ||
const STATE_FILE: &str = "state.toml"; | ||
|
||
const ONE_UNIT: u64 = 1_000_000_000_000_000_000; | ||
const ONE_MILLION: u64 = 1_000_000; | ||
|
||
pub static WEGLD_TOKEN_ID: &[u8] = b"WEGLD-a28c59"; | ||
pub static MEX_TOKEN_ID: &[u8] = b"MEX-a659d0"; | ||
pub static ONE_TOKEN_ID: &[u8] = b"ONE-83a7c0"; | ||
pub static USDC_TOKEN_ID: &[u8] = b"USDC-350c4e"; | ||
pub static UTK_TOKEN_ID: &[u8] = b"UTK-14d57d"; | ||
|
||
pub const SWAP_TOKENS_FIXED_INPUT_FUNC_NAME: &[u8] = b"swapTokensFixedInput"; | ||
pub const SWAP_TOKENS_FIXED_OUTPUT_FUNC_NAME: &[u8] = b"swapTokensFixedOutput"; | ||
|
||
#[tokio::main] | ||
async fn main() { | ||
env_logger::init(); | ||
|
||
let mut args = std::env::args(); | ||
let _ = args.next(); | ||
let cmd = args.next().expect("at least one argument required"); | ||
let mut interact = ContractInteract::new().await; | ||
match cmd.as_str() { | ||
"deploy" => interact.deploy().await, | ||
"forwardExecution" => interact.forward_execution().await, | ||
_ => panic!("unknown command: {}", &cmd), | ||
} | ||
} | ||
|
||
#[derive(Debug, Default, Serialize, Deserialize)] | ||
struct State { | ||
contract_address: Option<Bech32Address>, | ||
} | ||
|
||
impl State { | ||
// Deserializes state from file | ||
pub fn load_state() -> Self { | ||
if Path::new(STATE_FILE).exists() { | ||
let mut file = std::fs::File::open(STATE_FILE).unwrap(); | ||
let mut content = String::new(); | ||
file.read_to_string(&mut content).unwrap(); | ||
toml::from_str(&content).unwrap() | ||
} else { | ||
Self::default() | ||
} | ||
} | ||
|
||
/// Sets the contract address | ||
pub fn set_address(&mut self, address: Bech32Address) { | ||
self.contract_address = Some(address); | ||
} | ||
|
||
/// Returns the contract address | ||
pub fn current_address(&self) -> &Bech32Address { | ||
self.contract_address | ||
.as_ref() | ||
.expect("no known contract, deploy first") | ||
} | ||
} | ||
|
||
impl Drop for State { | ||
// Serializes state to file | ||
fn drop(&mut self) { | ||
let mut file = std::fs::File::create(STATE_FILE).unwrap(); | ||
file.write_all(toml::to_string(self).unwrap().as_bytes()) | ||
.unwrap(); | ||
} | ||
} | ||
|
||
struct ContractInteract { | ||
interactor: Interactor, | ||
wallet_address: Address, | ||
contract_code: BytesValue, | ||
config: Config, | ||
state: State, | ||
} | ||
|
||
impl ContractInteract { | ||
async fn new() -> Self { | ||
let mut interactor = Interactor::new(GATEWAY).await; | ||
let wallet_address = interactor.register_wallet(test_wallets::alice()); | ||
|
||
let contract_code = BytesValue::interpret_from( | ||
"mxsc:../output/paymaster.mxsc.json", | ||
&InterpreterContext::default(), | ||
); | ||
|
||
ContractInteract { | ||
interactor, | ||
wallet_address, | ||
contract_code, | ||
config: Config::load_config(), | ||
state: State::load_state(), | ||
} | ||
} | ||
|
||
async fn deploy(&mut self) { | ||
let new_address = self | ||
.interactor | ||
.tx() | ||
.from(&self.wallet_address) | ||
.gas(30_000_000u64) | ||
.typed(proxy::PaymasterContractProxy) | ||
.init() | ||
.code(&self.contract_code) | ||
.returns(ReturnsNewAddress) | ||
.prepare_async() | ||
.run() | ||
.await; | ||
let new_address_bech32 = bech32::encode(&new_address); | ||
self.state.set_address(Bech32Address::from_bech32_string( | ||
new_address_bech32.clone(), | ||
)); | ||
|
||
println!("new address: {new_address_bech32}"); | ||
} | ||
|
||
async fn forward_execution(&mut self) { | ||
let token_nonce = 0u64; | ||
let token_amount = BigUint::<StaticApi>::from(ONE_UNIT) * ONE_MILLION; | ||
|
||
let relayer_addr = &self.config.relayer_addr; | ||
|
||
let dest = &self.config.egld_mex_pair_address; | ||
let endpoint_name = ManagedBuffer::new_from_bytes(SWAP_TOKENS_FIXED_INPUT_FUNC_NAME); | ||
let endpoint_args = MultiValueVec::from(vec![ | ||
ManagedBuffer::new_from_bytes(WEGLD_TOKEN_ID), | ||
ManagedBuffer::new_from_bytes(b"1"), | ||
]); | ||
|
||
let mut payments = ManagedVec::<StaticApi, EsdtTokenPayment<StaticApi>>::new(); | ||
payments.push(EsdtTokenPayment::new( | ||
TokenIdentifier::from(WEGLD_TOKEN_ID), | ||
token_nonce, | ||
BigUint::<StaticApi>::from(ONE_UNIT / 100), // 0.01 WEGLD | ||
)); | ||
payments.push(EsdtTokenPayment::new( | ||
TokenIdentifier::from(MEX_TOKEN_ID), | ||
token_nonce, | ||
token_amount, // 1_000_000 MEX | ||
)); | ||
|
||
let response = self | ||
.interactor | ||
.tx() | ||
.from(&self.wallet_address) | ||
.to(self.state.current_address()) | ||
.gas(30_000_000u64) | ||
.typed(proxy::PaymasterContractProxy) | ||
.forward_execution(relayer_addr, dest, endpoint_name, endpoint_args) | ||
.payment(payments) | ||
.returns(ReturnsResultUnmanaged) | ||
.prepare_async() | ||
.run() | ||
.await; | ||
|
||
println!("Result: {response:?}"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
use multiversx_sc_snippets::imports::Bech32Address; | ||
use serde::Deserialize; | ||
use std::io::Read; | ||
|
||
/// Config file | ||
const CONFIG_FILE: &str = "config.toml"; | ||
|
||
/// Multisig Interact configuration | ||
#[derive(Debug, Deserialize)] | ||
pub struct Config { | ||
pub relayer_addr: Bech32Address, | ||
pub egld_mex_pair_address: Bech32Address, | ||
} | ||
|
||
impl Config { | ||
// Deserializes config from file | ||
pub fn load_config() -> Self { | ||
let mut file = std::fs::File::open(CONFIG_FILE).unwrap(); | ||
let mut content = String::new(); | ||
file.read_to_string(&mut content).unwrap(); | ||
toml::from_str(&content).unwrap() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// Code generated by the multiversx-sc proxy generator. DO NOT EDIT. | ||
|
||
//////////////////////////////////////////////////// | ||
////////////////// AUTO-GENERATED ////////////////// | ||
//////////////////////////////////////////////////// | ||
|
||
#![allow(dead_code)] | ||
#![allow(clippy::all)] | ||
|
||
use multiversx_sc::proxy_imports::*; | ||
|
||
pub struct PaymasterContractProxy; | ||
|
||
impl<Env, From, To, Gas> TxProxyTrait<Env, From, To, Gas> for PaymasterContractProxy | ||
where | ||
Env: TxEnv, | ||
From: TxFrom<Env>, | ||
To: TxTo<Env>, | ||
Gas: TxGas<Env>, | ||
{ | ||
type TxProxyMethods = PaymasterContractProxyMethods<Env, From, To, Gas>; | ||
|
||
fn proxy_methods(self, tx: Tx<Env, From, To, (), Gas, (), ()>) -> Self::TxProxyMethods { | ||
PaymasterContractProxyMethods { wrapped_tx: tx } | ||
} | ||
} | ||
|
||
pub struct PaymasterContractProxyMethods<Env, From, To, Gas> | ||
where | ||
Env: TxEnv, | ||
From: TxFrom<Env>, | ||
To: TxTo<Env>, | ||
Gas: TxGas<Env>, | ||
{ | ||
wrapped_tx: Tx<Env, From, To, (), Gas, (), ()>, | ||
} | ||
|
||
#[rustfmt::skip] | ||
impl<Env, From, Gas> PaymasterContractProxyMethods<Env, From, (), Gas> | ||
where | ||
Env: TxEnv, | ||
Env::Api: VMApi, | ||
From: TxFrom<Env>, | ||
Gas: TxGas<Env>, | ||
{ | ||
pub fn init( | ||
self, | ||
) -> TxTypedDeploy<Env, From, NotPayable, Gas, ()> { | ||
self.wrapped_tx | ||
.payment(NotPayable) | ||
.raw_deploy() | ||
.original_result() | ||
} | ||
} | ||
|
||
#[rustfmt::skip] | ||
impl<Env, From, To, Gas> PaymasterContractProxyMethods<Env, From, To, Gas> | ||
where | ||
Env: TxEnv, | ||
Env::Api: VMApi, | ||
From: TxFrom<Env>, | ||
To: TxTo<Env>, | ||
Gas: TxGas<Env>, | ||
{ | ||
pub fn forward_execution< | ||
Arg0: ProxyArg<ManagedAddress<Env::Api>>, | ||
Arg1: ProxyArg<ManagedAddress<Env::Api>>, | ||
Arg2: ProxyArg<ManagedBuffer<Env::Api>>, | ||
Arg3: ProxyArg<MultiValueEncoded<Env::Api, ManagedBuffer<Env::Api>>>, | ||
>( | ||
self, | ||
relayer_addr: Arg0, | ||
dest: Arg1, | ||
endpoint_name: Arg2, | ||
endpoint_args: Arg3, | ||
) -> TxTypedCall<Env, From, To, (), Gas, ()> { | ||
self.wrapped_tx | ||
.raw_call("forwardExecution") | ||
.argument(&relayer_addr) | ||
.argument(&dest) | ||
.argument(&endpoint_name) | ||
.argument(&endpoint_args) | ||
.original_result() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
contract_address = "erd1qqqqqqqqqqqqqpgqgr7585knhje7ns7w662pptwtjc03hn34d8sspl0nd4" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,6 @@ | ||
[[proxy]] | ||
path = "src/paymaster_proxy.rs" | ||
|
||
[[proxy]] | ||
path = "interactor/src/proxy.rs" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters