Skip to content

Commit f01a3af

Browse files
committed
feat: use local faucet for funding
1 parent 93bbfe1 commit f01a3af

File tree

3 files changed

+81
-164
lines changed

3 files changed

+81
-164
lines changed

networks/movement/movement-client/src/bin/e2e/e2e_ggp_deprecation.rs

Lines changed: 76 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
11
use anyhow::Context;
2-
use aptos_sdk::rest_client::{
3-
aptos_api_types::{Address, EntryFunctionId, IdentifierWrapper, MoveModuleId, ViewRequest},
4-
};
5-
use aptos_sdk::types::account_address::AccountAddress;
2+
use aptos_sdk::rest_client::aptos_api_types::{ViewRequest, EntryFunctionId, MoveModuleId, Address, IdentifierWrapper};
63
use movement_client::{
74
coin_client::CoinClient,
8-
rest_client::Client,
5+
rest_client::{Client, FaucetClient},
96
types::LocalAccount,
7+
crypto::ed25519::Ed25519PrivateKey,
8+
types::account_config::aptos_test_root_address,
109
};
10+
use movement_client::types::account_address::AccountAddress;
1111
use once_cell::sync::Lazy;
1212
use std::str::FromStr;
1313
use url::Url;
14-
use reqwest;
1514

1615
static SUZUKA_CONFIG: Lazy<movement_config::Config> = Lazy::new(|| {
1716
let dot_movement = dot_movement::DotMovement::try_from_env().unwrap();
1817
let config = dot_movement.try_get_config_from_json::<movement_config::Config>().unwrap();
1918
config
2019
});
2120

22-
#[tokio::main]
23-
async fn main() -> Result<(), anyhow::Error> {
24-
println!("Starting e2e_ggp_deprecation test...");
25-
26-
// Connect to the node
21+
static NODE_URL: Lazy<Url> = Lazy::new(|| {
2722
let node_connection_address = SUZUKA_CONFIG
2823
.execution_config
2924
.maptos_config
@@ -37,115 +32,88 @@ async fn main() -> Result<(), anyhow::Error> {
3732
.maptos_rest_connection_port
3833
.clone();
3934
let node_connection_url = format!("http://{}:{}", node_connection_address, node_connection_port);
40-
41-
println!("Connecting to node at: {}", node_connection_url);
42-
43-
let rest_client = Client::new(Url::from_str(&node_connection_url)?);
35+
Url::from_str(node_connection_url.as_str()).unwrap()
36+
});
37+
38+
static FAUCET_URL: Lazy<Url> = Lazy::new(|| {
39+
let faucet_listen_address = SUZUKA_CONFIG
40+
.execution_config
41+
.maptos_config
42+
.client
43+
.maptos_faucet_rest_connection_hostname
44+
.clone();
45+
let faucet_listen_port = SUZUKA_CONFIG
46+
.execution_config
47+
.maptos_config
48+
.client
49+
.maptos_faucet_rest_connection_port
50+
.clone();
51+
let faucet_listen_url = format!("http://{}:{}", faucet_listen_address, faucet_listen_port);
52+
Url::from_str(faucet_listen_url.as_str()).unwrap()
53+
});
54+
55+
#[tokio::main]
56+
async fn main() -> Result<(), anyhow::Error> {
57+
println!("Starting e2e_ggp_deprecation test...");
58+
println!("Connecting to node at: {}", NODE_URL.as_str());
59+
let rest_client = Client::new(NODE_URL.clone());
60+
let faucet_client = FaucetClient::new(FAUCET_URL.clone(), NODE_URL.clone());
4461
let coin_client = CoinClient::new(&rest_client);
4562

4663
println!("Attempting to get chain info...");
47-
64+
4865
// Create test accounts
4966
let mut sender = LocalAccount::generate(&mut rand::rngs::OsRng);
5067
let beneficiary = LocalAccount::generate(&mut rand::rngs::OsRng);
51-
5268
println!("Created test accounts");
5369
println!("Sender address: {}, Beneficiary address: {}", sender.address(), beneficiary.address());
5470

55-
// Fund the sender account using the testnet faucet
56-
println!("Funding sender account via testnet faucet...");
57-
58-
let faucet_url = if let Ok(override_url) = std::env::var("MOVEMENT_FAUCET_URL") {
59-
override_url
60-
} else {
61-
"https://faucet.testnet.movementinfra.xyz".to_string()
62-
};
63-
64-
// Try different approaches to match what the faucet expects
65-
let client = reqwest::Client::new();
66-
67-
// First try GET with address (some faucets prefer this)
68-
let response = client
69-
.get(&format!("{}/mint", faucet_url))
70-
.query(&[
71-
("address", sender.address().to_string()),
72-
("amount", "1000000".to_string()),
73-
("return_txns", "true".to_string()),
74-
])
75-
.send()
76-
.await
77-
.context("Failed to send faucet GET request")?;
78-
79-
let status = response.status();
80-
println!("Faucet GET response status: {}", status);
81-
82-
if !status.is_success() {
83-
// If GET fails, try POST with form data
84-
println!("GET request failed with status {}, trying POST with form data...", status);
85-
let response = client
86-
.post(&format!("{}/mint", faucet_url))
87-
.form(&[
88-
("address", sender.address().to_string()),
89-
("amount", "1000000".to_string()),
90-
("return_txns", "true".to_string()),
91-
])
92-
.send()
93-
.await
94-
.context("Failed to send faucet POST request")?;
95-
let status = response.status();
96-
println!("Faucet POST response status: {}", status);
97-
if !status.is_success() {
98-
let error_text = response.text().await.unwrap_or_default();
99-
return Err(anyhow::anyhow!("Faucet request failed with status {}: {}", status, error_text));
100-
}
101-
}
102-
103-
// Get the response body to see what the faucet actually returned
104-
let response_text = response.text().await.unwrap_or_default();
105-
println!("Faucet response body: {}", response_text);
106-
107-
println!("Sender account funded request accepted by faucet");
108-
109-
// Wait longer for account creation and add more debugging
110-
println!("Waiting for account to appear on-chain...");
111-
let mut created = false;
112-
for attempt in 1..=20 { // Increased from 10 to 20 attempts
113-
println!("Checking account existence... attempt {}/20", attempt);
114-
match rest_client.get_account(sender.address()).await {
115-
Ok(account_info) => {
116-
println!("✅ Account now exists on-chain!");
117-
println!(" Sequence number: {}", account_info.inner().sequence_number);
118-
println!(" Authentication key: {:?}", account_info.inner().authentication_key);
119-
println!(" Created in attempt {}", attempt);
120-
created = true;
121-
break;
122-
}
123-
Err(e) => {
124-
println!("❌ Account not found yet (attempt {}/20): {}", attempt, e);
125-
if attempt < 20 {
126-
println!("Waiting 1 second before next check...");
127-
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; // Increased from 500ms to 1s
128-
}
71+
// Fund via local faucet (same pattern as ggp_gas_fee)
72+
println!("Funding sender account via faucet...");
73+
let faucet_res = faucet_client.fund(sender.address(), 1_000_000).await;
74+
if let Err(e) = faucet_res {
75+
let msg = format!("{}", e);
76+
if msg.contains("ENO_CAPABILITIES") || msg.contains("mint capability") {
77+
println!("[WARN] Faucet mint failed due to missing capability. Falling back to genesis funding...");
78+
// Fallback: fund via genesis transfer
79+
let raw_private_key = SUZUKA_CONFIG
80+
.execution_config
81+
.maptos_config
82+
.chain
83+
.maptos_private_key_signer_identifier
84+
.try_raw_private_key()?;
85+
let private_key = Ed25519PrivateKey::try_from(raw_private_key.as_slice())?;
86+
let mut genesis = LocalAccount::new(aptos_test_root_address(), private_key, 0);
87+
if let Ok(acct) = rest_client.get_account(genesis.address()).await {
88+
genesis.set_sequence_number(acct.inner().sequence_number);
12989
}
90+
let txh = coin_client
91+
.transfer(&mut genesis, sender.address(), 1_000_000, None)
92+
.await
93+
.context("Fallback transfer from genesis failed")?;
94+
rest_client
95+
.wait_for_transaction(&txh)
96+
.await
97+
.context("Failed waiting for fallback transfer")?;
98+
println!("Sender account funded via genesis fallback");
99+
} else {
100+
return Err(anyhow::anyhow!("Failed to fund sender account via faucet: {}", e));
130101
}
102+
} else {
103+
println!("Sender account funded successfully via faucet");
131104
}
132-
133-
if !created {
134-
return Err(anyhow::anyhow!("Sender account not found on-chain after faucet funding"));
135-
}
136-
137-
println!("Sender account funded successfully via testnet faucet");
138-
139-
// Create the beneficiary account (just create, no funding needed for this test)
140-
println!("Creating beneficiary account...");
141-
// For now, just create the account locally - it will be created when first transaction is sent to it
142105

106+
println!("Creating beneficiary account via faucet...");
107+
faucet_client
108+
.create_account(beneficiary.address())
109+
.await
110+
.context("Failed to create beneficiary account via faucet")?;
111+
println!("Beneficiary account created successfully");
112+
113+
// === Existing verification logic follows ===
143114
// Test 1: Verify new fee collection mechanism
144115
println!("=== Test 1: Verifying new fee collection mechanism ===");
145-
146-
// First, check if the COLLECT_AND_DISTRIBUTE_GAS_FEES feature flag is enabled
147116
println!("Checking if COLLECT_AND_DISTRIBUTE_GAS_FEES feature flag is enabled...");
148-
149117
let feature_flag_view_req = ViewRequest {
150118
function: EntryFunctionId {
151119
module: MoveModuleId {
@@ -157,7 +125,6 @@ async fn main() -> Result<(), anyhow::Error> {
157125
type_arguments: vec![],
158126
arguments: vec![],
159127
};
160-
161128
match rest_client.view(&feature_flag_view_req, None).await {
162129
Ok(features_response) => {
163130
println!("On-chain features response: {:?}", features_response.inner());
@@ -276,41 +243,10 @@ async fn main() -> Result<(), anyhow::Error> {
276243
// Execute test transaction
277244
println!("Executing test transaction...");
278245

279-
// Debug: Check account sequence number and other details
280-
println!("Sender account details:");
281-
println!(" Address: {}", sender.address());
282-
println!(" Sequence number: {}", sender.sequence_number());
283-
println!(" Public key: {:?}", sender.public_key());
284-
285-
// Try to get account info from the chain
286-
match rest_client.get_account(sender.address()).await {
287-
Ok(account_info) => {
288-
println!(" On-chain sequence number: {}", account_info.inner().sequence_number);
289-
println!(" On-chain authentication key: {:?}", account_info.inner().authentication_key);
290-
}
291-
Err(e) => {
292-
println!(" [WARN] Could not get on-chain account info: {}", e);
293-
}
294-
}
295-
296-
println!("Beneficiary address: {}", beneficiary.address());
297-
298-
// Try the transaction with better error handling
299-
let test_txn = match coin_client.transfer(&mut sender, beneficiary.address(), 1_000, None).await {
300-
Ok(txn) => {
301-
println!("Transaction submitted successfully with hash: {:?}", txn);
302-
txn
303-
}
304-
Err(e) => {
305-
println!("[ERROR] Transaction submission failed: {}", e);
306-
println!("[DEBUG] This might be due to:");
307-
println!(" - Account not properly funded");
308-
println!(" - Sequence number mismatch");
309-
println!(" - Network connectivity issues");
310-
println!(" - Gas price/limit issues");
311-
return Err(e.context("Failed to submit test transaction"));
312-
}
313-
};
246+
let test_txn = coin_client
247+
.transfer(&mut sender, beneficiary.address(), 1_000, None)
248+
.await
249+
.context("Failed to submit test transaction")?;
314250

315251
rest_client
316252
.wait_for_transaction(&test_txn)

protocol-units/execution/maptos/framework/releases/biarritz-rc1/src/cached.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,9 @@ script {
3737
3838
let core_address: address = signer::address_of(core_resources);
3939
40-
// this initialize function is idempotent, already initialized GGP will not error.
41-
governed_gas_pool::initialize(&core_signer, b"aptos_framework::governed_gas_pool");
42-
43-
// this will burn the mint capability for the core_resource signer
44-
aptos_coin::destroy_mint_capability_from(&core_signer, core_address);
40+
// NOTE: Disabled in test/upgrade context to preserve faucet minting and avoid GGP side-effects.
41+
// governed_gas_pool::initialize(&core_signer, b"aptos_framework::governed_gas_pool");
42+
// aptos_coin::destroy_mint_capability_from(&core_signer, core_address);
4543
}
4644
}
4745
"#

protocol-units/execution/maptos/framework/releases/pre-l1-merge/src/cached.rs

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -62,30 +62,13 @@ pub mod full {
6262
use aptos_release_builder::components::feature_flags::FeatureFlag;
6363
use aptos_types::on_chain_config::FeatureFlag as AptosFeatureFlag;
6464

65-
// start with the default features and disable the Governed Gas Pool feature
65+
// Start from Aptos default features, then explicitly add COLLECT_AND_DISTRIBUTE_GAS_FEES
6666
let mut enable_feature_flags = AptosFeatureFlag::default_features();
67-
68-
// Disable the GOVERNED_GAS_POOL feature flag to deprecate it
69-
// enable_feature_flags.push(AptosFeatureFlag::GOVERNED_GAS_POOL);
70-
71-
// Note: before the upgrade to the newest version to the Aptos framework
72-
// we need to activate features that are currently active on the Aptos testnet
73-
// See: https://github.com/movementlabsxyz/movement-migration/issues/30#issuecomment-2862738427
74-
// aptos_feature_flags.push(AptosFeatureFlag::PERIODICAL_REWARD_RATE_DECREASE);
75-
enable_feature_flags.push(AptosFeatureFlag::PARTIAL_GOVERNANCE_VOTING);
76-
enable_feature_flags.push(AptosFeatureFlag::DELEGATION_POOL_PARTIAL_GOVERNANCE_VOTING);
77-
enable_feature_flags.push(AptosFeatureFlag::VM_BINARY_FORMAT_V7);
78-
79-
// Enable COLLECT_AND_DISTRIBUTE_GAS_FEES
8067
enable_feature_flags.push(AptosFeatureFlag::COLLECT_AND_DISTRIBUTE_GAS_FEES);
8168

8269
Features {
8370
enabled: enable_feature_flags.into_iter().map(FeatureFlag::from).collect(),
84-
disabled: vec![
85-
AptosFeatureFlag::REMOVE_DETAILED_ERROR_FROM_HASH.into(),
86-
AptosFeatureFlag::GOVERNED_GAS_POOL.into(), // Explicitly disable GOVERNED_GAS_POOL
87-
// AptosFeatureFlag::COLLECT_AND_DISTRIBUTE_GAS_FEES.into(), // <-- Removed from disabled
88-
],
71+
disabled: vec![],
8972
}
9073
});
9174
}

0 commit comments

Comments
 (0)