-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
iota-indexer: Add tests for TransactionBuilder api
- Loading branch information
Showing
2 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
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
277 changes: 277 additions & 0 deletions
277
crates/iota-indexer/tests/rpc-tests/transaction_builder.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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,277 @@ | ||
// Copyright (c) 2024 IOTA Stiftung | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
use iota_json_rpc_api::{ | ||
CoinReadApiClient, GovernanceReadApiClient, IndexerApiClient, ReadApiClient, | ||
TransactionBuilderClient, WriteApiClient, | ||
}; | ||
use iota_json_rpc_types::{ | ||
CoinPage, DelegatedStake, IotaObjectDataOptions, IotaObjectResponseQuery, | ||
IotaTransactionBlockResponseOptions, ObjectsPage, StakeStatus, TransactionBlockBytes, | ||
}; | ||
use iota_test_transaction_builder::TestTransactionBuilder; | ||
use iota_types::{ | ||
balance::Balance, | ||
base_types::{IotaAddress, ObjectID, ObjectRef}, | ||
crypto::{AccountKeyPair, get_key_pair}, | ||
object::Owner, | ||
programmable_transaction_builder::ProgrammableTransactionBuilder, | ||
utils::to_sender_signed_transaction, | ||
}; | ||
use jsonrpsee::http_client::HttpClient; | ||
use test_cluster::TestCluster; | ||
|
||
use crate::common::{ | ||
ApiTestSetup, indexer_wait_for_checkpoint, indexer_wait_for_object, | ||
indexer_wait_for_transaction, | ||
}; | ||
|
||
const FUNDED_BALANCE_PER_COIN: u64 = 10_000_000_000; | ||
|
||
#[test] | ||
fn transfer_object() { | ||
let ApiTestSetup { | ||
runtime, | ||
store, | ||
client, | ||
cluster, | ||
} = ApiTestSetup::get_or_init(); | ||
|
||
runtime.block_on(async move { | ||
indexer_wait_for_checkpoint(store, 1).await; | ||
|
||
let (sender, keypair): (_, AccountKeyPair) = get_key_pair(); | ||
let (receiver, _): (_, AccountKeyPair) = get_key_pair(); | ||
|
||
let sender_coins = create_coins_for_addr(cluster, client, sender, 2).await; | ||
let gas = sender_coins[0]; | ||
let object_to_send = sender_coins[1]; | ||
|
||
let tx_bytes = client | ||
.transfer_object( | ||
sender, | ||
object_to_send, | ||
Some(gas), | ||
100_000_000.into(), | ||
receiver, | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
let txn = to_sender_signed_transaction(tx_bytes.to_data().unwrap(), &keypair); | ||
let res = cluster.wallet.execute_transaction_must_succeed(txn).await; | ||
indexer_wait_for_transaction(res.digest, store, client).await; | ||
|
||
let transferred_object = client | ||
.get_object(object_to_send, Some(IotaObjectDataOptions::full_content())) | ||
.await | ||
.unwrap(); | ||
|
||
assert_eq!( | ||
transferred_object.owner(), | ||
Some(Owner::AddressOwner(receiver)) | ||
); | ||
}); | ||
} | ||
|
||
#[test] | ||
fn transfer_iota() { | ||
let ApiTestSetup { | ||
runtime, | ||
store, | ||
client, | ||
cluster, | ||
} = ApiTestSetup::get_or_init(); | ||
|
||
runtime.block_on(async move { | ||
indexer_wait_for_checkpoint(store, 1).await; | ||
|
||
let (sender, keypair): (_, AccountKeyPair) = get_key_pair(); | ||
let (receiver, _): (_, AccountKeyPair) = get_key_pair(); | ||
|
||
let sender_coins = create_coins_for_addr(cluster, client, sender, 1).await; | ||
let gas = sender_coins[0]; | ||
let transferred_balance = 100_000; | ||
|
||
let tx_bytes = client | ||
.transfer_iota( | ||
sender, | ||
gas, | ||
100_000_000.into(), | ||
receiver, | ||
Some(transferred_balance.into()), | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
let txn = to_sender_signed_transaction(tx_bytes.to_data().unwrap(), &keypair); | ||
let res = cluster.wallet.execute_transaction_must_succeed(txn).await; | ||
indexer_wait_for_transaction(res.digest, store, client).await; | ||
|
||
let receiver_balances = get_address_balances(client, receiver).await; | ||
|
||
assert_eq!(receiver_balances, [transferred_balance]); | ||
}); | ||
} | ||
|
||
#[test] | ||
fn pay() { | ||
let ApiTestSetup { | ||
runtime, | ||
store, | ||
client, | ||
cluster, | ||
} = ApiTestSetup::get_or_init(); | ||
|
||
runtime.block_on(async move { | ||
indexer_wait_for_checkpoint(store, 1).await; | ||
|
||
let (sender, keypair): (_, AccountKeyPair) = get_key_pair(); | ||
let (receiver_1, _): (_, AccountKeyPair) = get_key_pair(); | ||
let (receiver_2, _): (_, AccountKeyPair) = get_key_pair(); | ||
|
||
let input_coins: u64 = 3; | ||
let sender_coins = | ||
create_coins_for_addr(cluster, client, sender, input_coins as u32 + 1).await; | ||
let total_input_coins_balance = FUNDED_BALANCE_PER_COIN * input_coins; | ||
let transferred_balance_1 = total_input_coins_balance / 2 - 100; | ||
let transferred_balance_2 = total_input_coins_balance / 2 - 700; | ||
|
||
let tx_bytes = client | ||
.pay( | ||
sender, | ||
sender_coins[0..input_coins as usize].into(), | ||
[receiver_1, receiver_2].into(), | ||
[transferred_balance_1.into(), transferred_balance_2.into()].into(), | ||
None, // let node find the gas automatically | ||
100_000_000.into(), | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
let txn = to_sender_signed_transaction(tx_bytes.to_data().unwrap(), &keypair); | ||
let res = cluster.wallet.execute_transaction_must_succeed(txn).await; | ||
indexer_wait_for_transaction(res.digest, store, client).await; | ||
|
||
let receiver_1_balances = get_address_balances(client, receiver_1).await; | ||
let receiver_2_balances = get_address_balances(client, receiver_2).await; | ||
|
||
assert_eq!(receiver_1_balances, [transferred_balance_1]); | ||
assert_eq!(receiver_2_balances, [transferred_balance_2]); | ||
}); | ||
} | ||
|
||
#[test] | ||
fn pay_iota() { | ||
let ApiTestSetup { | ||
runtime, | ||
store, | ||
client, | ||
cluster, | ||
} = ApiTestSetup::get_or_init(); | ||
|
||
runtime.block_on(async move { | ||
indexer_wait_for_checkpoint(store, 1).await; | ||
|
||
let (sender, keypair): (_, AccountKeyPair) = get_key_pair(); | ||
let (receiver_1, _): (_, AccountKeyPair) = get_key_pair(); | ||
let (receiver_2, _): (_, AccountKeyPair) = get_key_pair(); | ||
|
||
let input_coins: u64 = 3; | ||
let sender_coins = create_coins_for_addr(cluster, client, sender, input_coins as u32).await; | ||
let gas_budget = 100_000_000; | ||
let total_available_input_coins_balance: u64 = | ||
FUNDED_BALANCE_PER_COIN * input_coins - gas_budget; | ||
let transferred_balance_1 = total_available_input_coins_balance / 2 - 100; | ||
let transferred_balance_2 = total_available_input_coins_balance / 2 - 700; | ||
|
||
let tx_bytes = client | ||
.pay_iota( | ||
sender, | ||
sender_coins.into(), | ||
[receiver_1, receiver_2].into(), | ||
[transferred_balance_1.into(), transferred_balance_2.into()].into(), | ||
gas_budget.into(), | ||
) | ||
.await | ||
.unwrap(); | ||
|
||
let txn = to_sender_signed_transaction(tx_bytes.to_data().unwrap(), &keypair); | ||
let res = cluster.wallet.execute_transaction_must_succeed(txn).await; | ||
indexer_wait_for_transaction(res.digest, store, client).await; | ||
|
||
let receiver_1_balances = get_address_balances(client, receiver_1).await; | ||
let receiver_2_balances = get_address_balances(client, receiver_2).await; | ||
|
||
assert_eq!(receiver_1_balances, [transferred_balance_1]); | ||
assert_eq!(receiver_2_balances, [transferred_balance_2]); | ||
}); | ||
} | ||
|
||
#[test] | ||
fn pay_all_iota() { | ||
let ApiTestSetup { | ||
runtime, | ||
store, | ||
client, | ||
cluster, | ||
} = ApiTestSetup::get_or_init(); | ||
|
||
runtime.block_on(async move { | ||
indexer_wait_for_checkpoint(store, 1).await; | ||
|
||
let (sender, keypair): (_, AccountKeyPair) = get_key_pair(); | ||
let (receiver, _): (_, AccountKeyPair) = get_key_pair(); | ||
|
||
let input_coins: u64 = 3; | ||
let sender_coins = create_coins_for_addr(cluster, client, sender, input_coins as u32).await; | ||
let gas_budget = 100_000_000; | ||
|
||
let tx_bytes = client | ||
.pay_all_iota(sender, sender_coins.into(), receiver, gas_budget.into()) | ||
.await | ||
.unwrap(); | ||
|
||
let txn = to_sender_signed_transaction(tx_bytes.to_data().unwrap(), &keypair); | ||
let res = cluster.wallet.execute_transaction_must_succeed(txn).await; | ||
indexer_wait_for_transaction(res.digest, store, client).await; | ||
|
||
let receiver_balances = get_address_balances(client, receiver).await; | ||
let expected_minimum_reciver_balance = FUNDED_BALANCE_PER_COIN * input_coins - gas_budget; | ||
|
||
assert_eq!(receiver_balances.len(), 1); | ||
assert!(receiver_balances[0] >= expected_minimum_reciver_balance); | ||
}); | ||
} | ||
|
||
async fn get_address_balances(indexer_client: &HttpClient, address: IotaAddress) -> Vec<u64> { | ||
indexer_client | ||
.get_coins(address, None, None, None) | ||
.await | ||
.unwrap() | ||
.data | ||
.iter() | ||
.map(|coin| coin.balance) | ||
.collect() | ||
} | ||
|
||
async fn create_coins_for_addr( | ||
cluster: &TestCluster, | ||
indexer_client: &HttpClient, | ||
address: IotaAddress, | ||
objects_count: u32, | ||
) -> Vec<ObjectID> { | ||
let mut coins: Vec<ObjectID> = Vec::new(); | ||
for _ in 0..objects_count { | ||
let coin = cluster | ||
.fund_address_and_return_gas( | ||
cluster.get_reference_gas_price().await, | ||
Some(FUNDED_BALANCE_PER_COIN), | ||
address, | ||
) | ||
.await; | ||
indexer_wait_for_object(indexer_client, coin.0, coin.1).await; | ||
coins.push(coin.0); | ||
} | ||
coins | ||
} |