add specific network/coin/balance types (#619)

* add specific network/coin/balance types

* misc fixes

* fix clippy

* misc fixes

* fix pr comments

* Make halting for external networks

* fix encode/decode
This commit is contained in:
akildemir
2024-10-07 05:16:11 +03:00
committed by GitHub
parent d7ecab605e
commit 435f1d9ae1
91 changed files with 1536 additions and 1055 deletions

View File

@@ -8,7 +8,7 @@ use blake2::{
use scale::Encode;
use serai_client::{
primitives::{Amount, NetworkId, Coin, Balance, BlockHash, SeraiAddress},
primitives::{Amount, BlockHash, ExternalBalance, ExternalCoin, SeraiAddress},
in_instructions::{
primitives::{InInstruction, InInstructionWithBalance, Batch},
InInstructionsEvent,
@@ -22,18 +22,17 @@ use common::in_instructions::provide_batch;
serai_test!(
publish_batch: (|serai: Serai| async move {
let network = NetworkId::Bitcoin;
let id = 0;
let mut block_hash = BlockHash([0; 32]);
OsRng.fill_bytes(&mut block_hash.0);
let mut address = SeraiAddress::new([0; 32]);
OsRng.fill_bytes(&mut address.0);
let coin = Coin::Bitcoin;
let coin = ExternalCoin::Bitcoin;
let network = coin.network();
let amount = Amount(OsRng.next_u64().saturating_add(1));
let balance = Balance { coin, amount };
let balance = ExternalBalance { coin, amount };
let batch = Batch {
network,
@@ -67,9 +66,9 @@ serai_test!(
let serai = serai.coins();
assert_eq!(
serai.mint_events().await.unwrap(),
vec![CoinsEvent::Mint { to: address, balance }]
vec![CoinsEvent::Mint { to: address, balance: balance.into() }]
);
assert_eq!(serai.coin_supply(coin).await.unwrap(), amount);
assert_eq!(serai.coin_balance(coin, address).await.unwrap(), amount);
assert_eq!(serai.coin_supply(coin.into()).await.unwrap(), amount);
assert_eq!(serai.coin_balance(coin.into(), address).await.unwrap(), amount);
})
);

View File

@@ -12,7 +12,7 @@ use sp_core::Pair;
use serai_client::{
primitives::{
Amount, NetworkId, Coin, Balance, BlockHash, SeraiAddress, Data, ExternalAddress,
Amount, ExternalCoin, ExternalBalance, BlockHash, SeraiAddress, Data, ExternalAddress,
insecure_pair_from_name,
},
in_instructions::{
@@ -28,9 +28,7 @@ use common::{tx::publish_tx, in_instructions::provide_batch};
serai_test!(
burn: (|serai: Serai| async move {
let network = NetworkId::Bitcoin;
let id = 0;
let mut block_hash = BlockHash([0; 32]);
OsRng.fill_bytes(&mut block_hash.0);
@@ -38,9 +36,10 @@ serai_test!(
let public = pair.public();
let address = SeraiAddress::from(public);
let coin = Coin::Bitcoin;
let coin = ExternalCoin::Bitcoin;
let network = coin.network();
let amount = Amount(OsRng.next_u64().saturating_add(1));
let balance = Balance { coin, amount };
let balance = ExternalBalance { coin, amount };
let batch = Batch {
network,
@@ -69,10 +68,10 @@ serai_test!(
assert_eq!(
serai.coins().mint_events().await.unwrap(),
vec![CoinsEvent::Mint { to: address, balance }]
vec![CoinsEvent::Mint { to: address, balance: balance.into() }]
);
assert_eq!(serai.coins().coin_supply(coin).await.unwrap(), amount);
assert_eq!(serai.coins().coin_balance(coin, address).await.unwrap(), amount);
assert_eq!(serai.coins().coin_supply(coin.into()).await.unwrap(), amount);
assert_eq!(serai.coins().coin_balance(coin.into(), address).await.unwrap(), amount);
// Now burn it
let mut rand_bytes = vec![0; 32];
@@ -99,7 +98,7 @@ serai_test!(
let serai = serai.coins();
let events = serai.burn_with_instruction_events().await.unwrap();
assert_eq!(events, vec![CoinsEvent::BurnWithInstruction { from: address, instruction }]);
assert_eq!(serai.coin_supply(coin).await.unwrap(), Amount(0));
assert_eq!(serai.coin_balance(coin, address).await.unwrap(), Amount(0));
assert_eq!(serai.coin_supply(coin.into()).await.unwrap(), Amount(0));
assert_eq!(serai.coin_balance(coin.into(), address).await.unwrap(), Amount(0));
})
);

View File

@@ -1,4 +1,4 @@
use serai_abi::primitives::{Coin, Amount};
use serai_abi::primitives::{Amount, Coin, ExternalCoin};
use serai_client::{Serai, SeraiDex};
use sp_core::{sr25519::Pair, Pair as PairTrait};
@@ -8,7 +8,7 @@ use crate::common::tx::publish_tx;
#[allow(dead_code)]
pub async fn add_liquidity(
serai: &Serai,
coin: Coin,
coin: ExternalCoin,
coin_amount: Amount,
sri_amount: Amount,
nonce: u32,

View File

@@ -11,11 +11,12 @@ use sp_core::{sr25519::Signature, Pair as PairTrait};
use serai_abi::{
genesis_liquidity::primitives::{oraclize_values_message, Values},
validator_sets::primitives::{musig_context, Session, ValidatorSet},
in_instructions::primitives::{InInstruction, InInstructionWithBalance, Batch},
in_instructions::primitives::{Batch, InInstruction, InInstructionWithBalance},
primitives::{
Amount, NetworkId, Coin, Balance, BlockHash, SeraiAddress, insecure_pair_from_name,
insecure_pair_from_name, Amount, ExternalBalance, BlockHash, ExternalCoin, ExternalNetworkId,
NetworkId, SeraiAddress, EXTERNAL_COINS,
},
validator_sets::primitives::{musig_context, Session, ValidatorSet},
};
use serai_client::{Serai, SeraiGenesisLiquidity};
@@ -25,12 +26,11 @@ use crate::common::{in_instructions::provide_batch, tx::publish_tx};
#[allow(dead_code)]
pub async fn set_up_genesis(
serai: &Serai,
coins: &[Coin],
values: &HashMap<Coin, u64>,
) -> (HashMap<Coin, Vec<(SeraiAddress, Amount)>>, HashMap<NetworkId, u32>) {
values: &HashMap<ExternalCoin, u64>,
) -> (HashMap<ExternalCoin, Vec<(SeraiAddress, Amount)>>, HashMap<ExternalNetworkId, u32>) {
// make accounts with amounts
let mut accounts = HashMap::new();
for coin in coins {
for coin in EXTERNAL_COINS {
// make 5 accounts per coin
let mut values = vec![];
for _ in 0 .. 5 {
@@ -38,18 +38,18 @@ pub async fn set_up_genesis(
OsRng.fill_bytes(&mut address.0);
values.push((address, Amount(OsRng.next_u64() % 10u64.pow(coin.decimals()))));
}
accounts.insert(*coin, values);
accounts.insert(coin, values);
}
// send a batch per coin
let mut batch_ids: HashMap<NetworkId, u32> = HashMap::new();
for coin in coins {
let mut batch_ids: HashMap<ExternalNetworkId, u32> = HashMap::new();
for coin in EXTERNAL_COINS {
// set up instructions
let instructions = accounts[coin]
let instructions = accounts[&coin]
.iter()
.map(|(addr, amount)| InInstructionWithBalance {
instruction: InInstruction::GenesisLiquidity(*addr),
balance: Balance { coin: *coin, amount: *amount },
balance: ExternalBalance { coin, amount: *amount },
})
.collect::<Vec<_>>();
@@ -73,8 +73,11 @@ pub async fn set_up_genesis(
// set values relative to each other. We can do that without checking for genesis period blocks
// since we are running in test(fast-epoch) mode.
// TODO: Random values here
let values =
Values { monero: values[&Coin::Monero], ether: values[&Coin::Ether], dai: values[&Coin::Dai] };
let values = Values {
monero: values[&ExternalCoin::Monero],
ether: values[&ExternalCoin::Ether],
dai: values[&ExternalCoin::Dai],
};
set_values(serai, &values).await;
(accounts, batch_ids)

View File

@@ -9,8 +9,8 @@ use scale::Encode;
use sp_core::Pair;
use serai_client::{
primitives::{insecure_pair_from_name, BlockHash, NetworkId, Balance, SeraiAddress},
validator_sets::primitives::{ValidatorSet, KeyPair},
primitives::{insecure_pair_from_name, BlockHash, ExternalBalance, SeraiAddress},
validator_sets::primitives::{ExternalValidatorSet, KeyPair},
in_instructions::{
primitives::{Batch, SignedBatch, batch_message, InInstruction, InInstructionWithBalance},
InInstructionsEvent,
@@ -23,8 +23,8 @@ use crate::common::{tx::publish_tx, validator_sets::set_keys};
#[allow(dead_code)]
pub async fn provide_batch(serai: &Serai, batch: Batch) -> [u8; 32] {
let serai_latest = serai.as_of_latest_finalized_block().await.unwrap();
let session = serai_latest.validator_sets().session(batch.network).await.unwrap().unwrap();
let set = ValidatorSet { session, network: batch.network };
let session = serai_latest.validator_sets().session(batch.network.into()).await.unwrap().unwrap();
let set = ExternalValidatorSet { session, network: batch.network };
let pair = insecure_pair_from_name(&format!("ValidatorSet {set:?}"));
let keys = if let Some(keys) = serai_latest.validator_sets().keys(set).await.unwrap() {
@@ -65,8 +65,7 @@ pub async fn provide_batch(serai: &Serai, batch: Batch) -> [u8; 32] {
#[allow(dead_code)]
pub async fn mint_coin(
serai: &Serai,
balance: Balance,
network: NetworkId,
balance: ExternalBalance,
batch_id: u32,
address: SeraiAddress,
) -> [u8; 32] {
@@ -74,7 +73,7 @@ pub async fn mint_coin(
OsRng.fill_bytes(&mut block_hash.0);
let batch = Batch {
network,
network: balance.coin.network(),
id: batch_id,
block: block_hash,
instructions: vec![InInstructionWithBalance {

View File

@@ -15,7 +15,7 @@ use schnorrkel::Schnorrkel;
use serai_client::{
validator_sets::{
primitives::{ValidatorSet, KeyPair, musig_context, set_keys_message},
primitives::{ExternalValidatorSet, KeyPair, musig_context, set_keys_message},
ValidatorSetsEvent,
},
Amount, Serai, SeraiValidatorSets,
@@ -26,7 +26,7 @@ use crate::common::tx::publish_tx;
#[allow(dead_code)]
pub async fn set_keys(
serai: &Serai,
set: ValidatorSet,
set: ExternalValidatorSet,
key_pair: KeyPair,
pairs: &[Pair],
) -> [u8; 32] {
@@ -46,7 +46,8 @@ pub async fn set_keys(
assert_eq!(Ristretto::generator() * secret_key, pub_keys[i]);
threshold_keys.push(
musig::<Ristretto>(&musig_context(set), &Zeroizing::new(secret_key), &pub_keys).unwrap(),
musig::<Ristretto>(&musig_context(set.into()), &Zeroizing::new(secret_key), &pub_keys)
.unwrap(),
);
}

View File

@@ -6,8 +6,8 @@ use serai_abi::in_instructions::primitives::DexCall;
use serai_client::{
primitives::{
Amount, NetworkId, Coin, Balance, BlockHash, insecure_pair_from_name, ExternalAddress,
SeraiAddress,
Amount, Coin, Balance, BlockHash, insecure_pair_from_name, ExternalAddress, SeraiAddress,
ExternalCoin, ExternalBalance,
},
in_instructions::primitives::{
InInstruction, InInstructionWithBalance, Batch, IN_INSTRUCTION_EXECUTOR, OutAddress,
@@ -28,15 +28,14 @@ use common::{
// TODO: Check Transfer events
serai_test!(
add_liquidity: (|serai: Serai| async move {
let coin = Coin::Monero;
let coin = ExternalCoin::Monero;
let pair = insecure_pair_from_name("Ferdie");
// mint sriXMR in the account so that we can add liq.
// Ferdie account is already pre-funded with SRI.
mint_coin(
&serai,
Balance { coin, amount: Amount(100_000_000_000_000) },
NetworkId::Monero,
ExternalBalance { coin, amount: Amount(100_000_000_000_000) },
0,
pair.clone().public().into(),
)
@@ -61,7 +60,7 @@ serai_test!(
vec![DexEvent::LiquidityAdded {
who: pair.public().into(),
mint_to: pair.public().into(),
pool_id: Coin::Monero,
pool_id: coin,
coin_amount: coin_amount.0,
sri_amount: sri_amount.0,
lp_token_minted: 49_999999990000
@@ -71,15 +70,14 @@ serai_test!(
// Tests coin -> SRI and SRI -> coin swaps.
swap_coin_to_sri: (|serai: Serai| async move {
let coin = Coin::Ether;
let coin = ExternalCoin::Ether;
let pair = insecure_pair_from_name("Ferdie");
// mint sriXMR in the account so that we can add liq.
// Ferdie account is already pre-funded with SRI.
mint_coin(
&serai,
Balance { coin, amount: Amount(100_000_000_000_000) },
NetworkId::Ethereum,
ExternalBalance { coin, amount: Amount(100_000_000_000_000) },
0,
pair.clone().public().into(),
)
@@ -96,14 +94,21 @@ serai_test!(
// now that we have our liquid pool, swap some coin to SRI.
let mut amount_in = Amount(25_000_000_000_000);
let mut block = common_swap(&serai, coin, Coin::Serai, amount_in, Amount(1), 1, pair.clone())
let mut block = common_swap(
&serai,
coin.into(),
Coin::Serai,
amount_in,
Amount(1),
1,
pair.clone())
.await;
// get only the swap events
let mut events = serai.as_of(block).dex().events().await.unwrap();
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
let mut path = BoundedVec::try_from(vec![coin, Coin::Serai]).unwrap();
let mut path = BoundedVec::try_from(vec![coin.into(), Coin::Serai]).unwrap();
assert_eq!(
events,
vec![DexEvent::SwapExecuted {
@@ -117,13 +122,21 @@ serai_test!(
// now swap some SRI to coin
amount_in = Amount(10_000_000_000_000);
block = common_swap(&serai, Coin::Serai, coin, amount_in, Amount(1), 2, pair.clone()).await;
block = common_swap(
&serai,
Coin::Serai,
coin.into(),
amount_in,
Amount(1),
2,
pair.clone()
).await;
// get only the swap events
let mut events = serai.as_of(block).dex().events().await.unwrap();
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
path = BoundedVec::try_from(vec![Coin::Serai, coin]).unwrap();
path = BoundedVec::try_from(vec![Coin::Serai, coin.into()]).unwrap();
assert_eq!(
events,
vec![DexEvent::SwapExecuted {
@@ -137,23 +150,21 @@ serai_test!(
})
swap_coin_to_coin: (|serai: Serai| async move {
let coin1 = Coin::Monero;
let coin2 = Coin::Dai;
let coin1 = ExternalCoin::Monero;
let coin2 = ExternalCoin::Dai;
let pair = insecure_pair_from_name("Ferdie");
// mint coins
mint_coin(
&serai,
Balance { coin: coin1, amount: Amount(100_000_000_000_000) },
NetworkId::Monero,
ExternalBalance { coin: coin1, amount: Amount(100_000_000_000_000) },
0,
pair.clone().public().into(),
)
.await;
mint_coin(
&serai,
Balance { coin: coin2, amount: Amount(100_000_000_000_000) },
NetworkId::Ethereum,
ExternalBalance { coin: coin2, amount: Amount(100_000_000_000_000) },
0,
pair.clone().public().into(),
)
@@ -177,13 +188,21 @@ serai_test!(
// swap coin1 -> coin2
let amount_in = Amount(25_000_000_000_000);
let block = common_swap(&serai, coin1, coin2, amount_in, Amount(1), 2, pair.clone()).await;
let block = common_swap(
&serai,
coin1.into(),
coin2.into(),
amount_in,
Amount(1),
2,
pair.clone()
).await;
// get only the swap events
let mut events = serai.as_of(block).dex().events().await.unwrap();
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
let path = BoundedVec::try_from(vec![coin1, Coin::Serai, coin2]).unwrap();
let path = BoundedVec::try_from(vec![coin1.into(), Coin::Serai, coin2.into()]).unwrap();
assert_eq!(
events,
vec![DexEvent::SwapExecuted {
@@ -197,7 +216,7 @@ serai_test!(
})
add_liquidity_in_instructions: (|serai: Serai| async move {
let coin = Coin::Bitcoin;
let coin = ExternalCoin::Bitcoin;
let pair = insecure_pair_from_name("Ferdie");
let mut batch_id = 0;
@@ -205,8 +224,7 @@ serai_test!(
// Ferdie account is already pre-funded with SRI.
mint_coin(
&serai,
Balance { coin, amount: Amount(100_000_000_000_000) },
NetworkId::Bitcoin,
ExternalBalance { coin, amount: Amount(100_000_000_000_000) },
batch_id,
pair.clone().public().into(),
)
@@ -227,12 +245,12 @@ serai_test!(
let mut block_hash = BlockHash([0; 32]);
OsRng.fill_bytes(&mut block_hash.0);
let batch = Batch {
network: NetworkId::Bitcoin,
network: coin.network(),
id: batch_id,
block: block_hash,
instructions: vec![InInstructionWithBalance {
instruction: InInstruction::Dex(DexCall::SwapAndAddLiquidity(pair.public().into())),
balance: Balance { coin: Coin::Bitcoin, amount: Amount(20_000_000_000_000) },
balance: ExternalBalance { coin, amount: Amount(20_000_000_000_000) },
}],
};
@@ -244,7 +262,7 @@ serai_test!(
vec![DexEvent::LiquidityAdded {
who: IN_INSTRUCTION_EXECUTOR,
mint_to: pair.public().into(),
pool_id: Coin::Bitcoin,
pool_id: coin,
coin_amount: 10_000_000_000_000, // half of sent amount
sri_amount: 111_333_778_668,
lp_token_minted: 1_054_092_553_383
@@ -253,8 +271,8 @@ serai_test!(
})
swap_in_instructions: (|serai: Serai| async move {
let coin1 = Coin::Monero;
let coin2 = Coin::Ether;
let coin1 = ExternalCoin::Monero;
let coin2 = ExternalCoin::Ether;
let pair = insecure_pair_from_name("Ferdie");
let mut coin1_batch_id = 0;
let mut coin2_batch_id = 0;
@@ -262,8 +280,7 @@ serai_test!(
// mint coins
mint_coin(
&serai,
Balance { coin: coin1, amount: Amount(10_000_000_000_000_000) },
NetworkId::Monero,
ExternalBalance { coin: coin1, amount: Amount(10_000_000_000_000_000) },
coin1_batch_id,
pair.clone().public().into(),
)
@@ -271,8 +288,7 @@ serai_test!(
coin1_batch_id += 1;
mint_coin(
&serai,
Balance { coin: coin2, amount: Amount(100_000_000_000_000) },
NetworkId::Ethereum,
ExternalBalance { coin: coin2, amount: Amount(100_000_000_000_000) },
coin2_batch_id,
pair.clone().public().into(),
)
@@ -305,18 +321,18 @@ serai_test!(
let out_address = OutAddress::External(ExternalAddress::new(rand_bytes.clone()).unwrap());
// amount is the min out amount
let out_balance = Balance { coin: coin2, amount: Amount(1) };
let out_balance = Balance { coin: coin2.into(), amount: Amount(1) };
// now that we have our pools, we can try to swap
let mut block_hash = BlockHash([0; 32]);
OsRng.fill_bytes(&mut block_hash.0);
let batch = Batch {
network: NetworkId::Monero,
network: coin1.network(),
id: coin1_batch_id,
block: block_hash,
instructions: vec![InInstructionWithBalance {
instruction: InInstruction::Dex(DexCall::Swap(out_balance, out_address)),
balance: Balance { coin: coin1, amount: Amount(200_000_000_000_000) },
balance: ExternalBalance { coin: coin1, amount: Amount(200_000_000_000_000) },
}],
};
@@ -325,7 +341,7 @@ serai_test!(
let mut events = serai.as_of(block).dex().events().await.unwrap();
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
let path = BoundedVec::try_from(vec![coin1, Coin::Serai, coin2]).unwrap();
let path = BoundedVec::try_from(vec![coin1.into(), Coin::Serai, coin2.into()]).unwrap();
assert_eq!(
events,
vec![DexEvent::SwapExecuted {
@@ -345,18 +361,18 @@ serai_test!(
OutAddress::Serai(SeraiAddress::new(rand_bytes.clone().try_into().unwrap()));
// amount is the min out amount
let out_balance = Balance { coin: coin1, amount: Amount(1) };
let out_balance = Balance { coin: coin1.into(), amount: Amount(1) };
// now that we have our pools, we can try to swap
let mut block_hash = BlockHash([0; 32]);
OsRng.fill_bytes(&mut block_hash.0);
let batch = Batch {
network: NetworkId::Ethereum,
network: coin2.network(),
id: coin2_batch_id,
block: block_hash,
instructions: vec![InInstructionWithBalance {
instruction: InInstruction::Dex(DexCall::Swap(out_balance, out_address.clone())),
balance: Balance { coin: coin2, amount: Amount(200_000_000_000) },
balance: ExternalBalance { coin: coin2, amount: Amount(200_000_000_000) },
}],
};
@@ -364,7 +380,7 @@ serai_test!(
let mut events = serai.as_of(block).dex().events().await.unwrap();
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
let path = BoundedVec::try_from(vec![coin2, Coin::Serai, coin1]).unwrap();
let path = BoundedVec::try_from(vec![coin2.into(), Coin::Serai, coin1.into()]).unwrap();
assert_eq!(
events,
vec![DexEvent::SwapExecuted {
@@ -389,12 +405,12 @@ serai_test!(
let mut block_hash = BlockHash([0; 32]);
OsRng.fill_bytes(&mut block_hash.0);
let batch = Batch {
network: NetworkId::Monero,
network: coin1.network(),
id: coin1_batch_id,
block: block_hash,
instructions: vec![InInstructionWithBalance {
instruction: InInstruction::Dex(DexCall::Swap(out_balance, out_address.clone())),
balance: Balance { coin: coin1, amount: Amount(100_000_000_000_000) },
balance: ExternalBalance { coin: coin1, amount: Amount(100_000_000_000_000) },
}],
};
@@ -402,7 +418,7 @@ serai_test!(
let mut events = serai.as_of(block).dex().events().await.unwrap();
events.retain(|e| matches!(e, DexEvent::SwapExecuted { .. }));
let path = BoundedVec::try_from(vec![coin1, Coin::Serai]).unwrap();
let path = BoundedVec::try_from(vec![coin1.into(), Coin::Serai]).unwrap();
assert_eq!(
events,
vec![DexEvent::SwapExecuted {

View File

@@ -1,4 +1,4 @@
use serai_client::{primitives::NetworkId, Serai};
use serai_client::{primitives::ExternalNetworkId, Serai};
#[tokio::test]
async fn dht() {
@@ -44,7 +44,7 @@ async fn dht() {
assert!(!Serai::new(serai_rpc.clone())
.await
.unwrap()
.p2p_validators(NetworkId::Bitcoin)
.p2p_validators(ExternalNetworkId::Bitcoin.into())
.await
.unwrap()
.is_empty());

View File

@@ -7,16 +7,13 @@ use serai_abi::{
emissions::primitives::{INITIAL_REWARD_PER_BLOCK, SECURE_BY},
in_instructions::primitives::Batch,
primitives::{
BlockHash, Coin, COINS, FAST_EPOCH_DURATION, FAST_EPOCH_INITIAL_PERIOD, NETWORKS,
TARGET_BLOCK_TIME,
BlockHash, ExternalBalance, ExternalCoin, ExternalNetworkId, EXTERNAL_NETWORKS,
FAST_EPOCH_DURATION, FAST_EPOCH_INITIAL_PERIOD, NETWORKS, TARGET_BLOCK_TIME, Amount, NetworkId,
},
validator_sets::primitives::Session,
};
use serai_client::{
primitives::{Amount, NetworkId, Balance},
Serai,
};
use serai_client::Serai;
mod common;
use common::{genesis_liquidity::set_up_genesis, in_instructions::provide_batch};
@@ -27,31 +24,32 @@ serai_test_fast_epoch!(
})
);
async fn send_batches(serai: &Serai, ids: &mut HashMap<NetworkId, u32>) {
for network in NETWORKS {
if network != NetworkId::Serai {
// set up batch id
ids
.entry(network)
.and_modify(|v| {
*v += 1;
})
.or_insert(0);
async fn send_batches(serai: &Serai, ids: &mut HashMap<ExternalNetworkId, u32>) {
for network in EXTERNAL_NETWORKS {
// set up batch id
ids
.entry(network)
.and_modify(|v| {
*v += 1;
})
.or_insert(0);
// set up block hash
let mut block = BlockHash([0; 32]);
OsRng.fill_bytes(&mut block.0);
// set up block hash
let mut block = BlockHash([0; 32]);
OsRng.fill_bytes(&mut block.0);
provide_batch(serai, Batch { network, id: ids[&network], block, instructions: vec![] }).await;
}
provide_batch(serai, Batch { network, id: ids[&network], block, instructions: vec![] }).await;
}
}
async fn test_emissions(serai: Serai) {
// set up the genesis
let coins = COINS.into_iter().filter(|c| *c != Coin::native()).collect::<Vec<_>>();
let values = HashMap::from([(Coin::Monero, 184100), (Coin::Ether, 4785000), (Coin::Dai, 1500)]);
let (_, mut batch_ids) = set_up_genesis(&serai, &coins, &values).await;
let values = HashMap::from([
(ExternalCoin::Monero, 184100),
(ExternalCoin::Ether, 4785000),
(ExternalCoin::Dai, 1500),
]);
let (_, mut batch_ids) = set_up_genesis(&serai, &values).await;
// wait until genesis is complete
let mut genesis_complete_block = None;
@@ -144,7 +142,7 @@ async fn test_emissions(serai: Serai) {
}
/// Returns the required stake in terms SRI for a given `Balance`.
async fn required_stake(serai: &TemporalSerai<'_>, balance: Balance) -> u64 {
async fn required_stake(serai: &TemporalSerai<'_>, balance: ExternalBalance) -> u64 {
// This is inclusive to an increase in accuracy
let sri_per_coin = serai.dex().oracle_value(balance.coin).await.unwrap().unwrap_or(Amount(0));
@@ -208,18 +206,14 @@ async fn get_distances(
// we can check the supply to see how much coin hence liability we have.
let mut distances: HashMap<NetworkId, u64> = HashMap::new();
let mut total_distance = 0;
for n in NETWORKS {
if n == NetworkId::Serai {
continue;
}
for n in EXTERNAL_NETWORKS {
let mut required = 0;
for c in n.coins() {
let amount = serai.coins().coin_supply(*c).await.unwrap();
required += required_stake(serai, Balance { coin: *c, amount }).await;
let amount = serai.coins().coin_supply(c.into()).await.unwrap();
required += required_stake(serai, ExternalBalance { coin: c, amount }).await;
}
let mut current = *current_stake.get(&n).unwrap();
let mut current = *current_stake.get(&n.into()).unwrap();
if current > required {
current = required;
}
@@ -227,7 +221,7 @@ async fn get_distances(
let distance = required - current;
total_distance += distance;
distances.insert(n, distance);
distances.insert(n.into(), distance);
}
// add serai network portion(20%)

View File

@@ -2,7 +2,7 @@ use std::{time::Duration, collections::HashMap};
use serai_client::Serai;
use serai_abi::primitives::{Coin, COINS, Amount, GENESIS_SRI};
use serai_abi::primitives::{Amount, Coin, ExternalCoin, COINS, EXTERNAL_COINS, GENESIS_SRI};
use serai_client::genesis_liquidity::primitives::{
GENESIS_LIQUIDITY_ACCOUNT, INITIAL_GENESIS_LP_SHARES,
@@ -19,9 +19,12 @@ serai_test_fast_epoch!(
pub async fn test_genesis_liquidity(serai: Serai) {
// set up the genesis
let coins = COINS.into_iter().filter(|c| *c != Coin::native()).collect::<Vec<_>>();
let values = HashMap::from([(Coin::Monero, 184100), (Coin::Ether, 4785000), (Coin::Dai, 1500)]);
let (accounts, _) = set_up_genesis(&serai, &coins, &values).await;
let values = HashMap::from([
(ExternalCoin::Monero, 184100),
(ExternalCoin::Ether, 4785000),
(ExternalCoin::Dai, 1500),
]);
let (accounts, _) = set_up_genesis(&serai, &values).await;
// wait until genesis is complete
while serai
@@ -55,9 +58,9 @@ pub async fn test_genesis_liquidity(serai: Serai) {
// check pools has proper liquidity
let mut pool_amounts = HashMap::new();
let mut total_value = 0u128;
for coin in coins.clone() {
for coin in EXTERNAL_COINS {
let total_coin = accounts[&coin].iter().fold(0u128, |acc, value| acc + u128::from(value.1 .0));
let value = if coin != Coin::Bitcoin {
let value = if coin != ExternalCoin::Bitcoin {
(total_coin * u128::from(values[&coin])) / 10u128.pow(coin.decimals())
} else {
total_coin
@@ -69,8 +72,8 @@ pub async fn test_genesis_liquidity(serai: Serai) {
// check distributed SRI per pool
let mut total_sri_distributed = 0u128;
for coin in coins.clone() {
let sri = if coin == *COINS.last().unwrap() {
for coin in EXTERNAL_COINS {
let sri = if coin == *EXTERNAL_COINS.last().unwrap() {
u128::from(GENESIS_SRI).checked_sub(total_sri_distributed).unwrap()
} else {
(pool_amounts[&coin].1 * u128::from(GENESIS_SRI)) / total_value
@@ -83,7 +86,7 @@ pub async fn test_genesis_liquidity(serai: Serai) {
}
// check each liquidity provider got liquidity tokens proportional to their value
for coin in coins {
for coin in EXTERNAL_COINS {
let liq_supply = serai.genesis_liquidity().supply(coin).await.unwrap();
for (acc, amount) in &accounts[&coin] {
let acc_liq_shares = serai.genesis_liquidity().liquidity(acc, coin).await.unwrap().shares;

View File

@@ -7,17 +7,18 @@ use sp_core::{
use serai_client::{
primitives::{
NETWORKS, NetworkId, BlockHash, insecure_pair_from_name, FAST_EPOCH_DURATION, TARGET_BLOCK_TIME,
NETWORKS, NetworkId, BlockHash, insecure_pair_from_name, FAST_EPOCH_DURATION,
TARGET_BLOCK_TIME, ExternalNetworkId, Amount,
},
validator_sets::{
primitives::{Session, ValidatorSet, KeyPair},
primitives::{Session, ValidatorSet, ExternalValidatorSet, KeyPair},
ValidatorSetsEvent,
},
in_instructions::{
primitives::{Batch, SignedBatch, batch_message},
SeraiInInstructions,
},
Amount, Serai,
Serai,
};
mod common;
@@ -58,8 +59,8 @@ async fn get_ordered_keys(serai: &Serai, network: NetworkId, accounts: &[Pair])
serai_test!(
set_keys_test: (|serai: Serai| async move {
let network = NetworkId::Bitcoin;
let set = ValidatorSet { session: Session(0), network };
let network = ExternalNetworkId::Bitcoin;
let set = ExternalValidatorSet { session: Session(0), network };
let pair = insecure_pair_from_name("Alice");
let public = pair.public();
@@ -89,7 +90,7 @@ serai_test!(
{
let vs_serai = serai.as_of_latest_finalized_block().await.unwrap();
let vs_serai = vs_serai.validator_sets();
let participants = vs_serai.participants(set.network).await
let participants = vs_serai.participants(set.network.into()).await
.unwrap()
.unwrap()
.into_iter()
@@ -197,9 +198,9 @@ async fn validator_set_rotation() {
// amounts for single key share per network
let key_shares = HashMap::from([
(NetworkId::Serai, Amount(50_000 * 10_u64.pow(8))),
(NetworkId::Bitcoin, Amount(1_000_000 * 10_u64.pow(8))),
(NetworkId::Monero, Amount(100_000 * 10_u64.pow(8))),
(NetworkId::Ethereum, Amount(1_000_000 * 10_u64.pow(8))),
(NetworkId::External(ExternalNetworkId::Bitcoin), Amount(1_000_000 * 10_u64.pow(8))),
(NetworkId::External(ExternalNetworkId::Monero), Amount(100_000 * 10_u64.pow(8))),
(NetworkId::External(ExternalNetworkId::Ethereum), Amount(1_000_000 * 10_u64.pow(8))),
]);
// genesis participants per network
@@ -208,9 +209,9 @@ async fn validator_set_rotation() {
accounts[.. 4].to_vec().iter().map(|pair| pair.public()).collect::<Vec<_>>();
let mut participants = HashMap::from([
(NetworkId::Serai, default_participants.clone()),
(NetworkId::Bitcoin, default_participants.clone()),
(NetworkId::Monero, default_participants.clone()),
(NetworkId::Ethereum, default_participants),
(NetworkId::External(ExternalNetworkId::Bitcoin), default_participants.clone()),
(NetworkId::External(ExternalNetworkId::Monero), default_participants.clone()),
(NetworkId::External(ExternalNetworkId::Ethereum), default_participants),
]);
// test the set rotation
@@ -237,7 +238,8 @@ async fn validator_set_rotation() {
// set the keys if it is an external set
if network != NetworkId::Serai {
let set = ValidatorSet { session: Session(0), network };
let set =
ExternalValidatorSet { session: Session(0), network: network.try_into().unwrap() };
let key_pair = get_random_key_pair();
let pairs = get_ordered_keys(&serai, network, &accounts).await;
set_keys(&serai, set, key_pair, &pairs).await;
@@ -265,7 +267,8 @@ async fn validator_set_rotation() {
if network != NetworkId::Serai {
// set the keys if it is an external set
let set = ValidatorSet { session: Session(1), network };
let set =
ExternalValidatorSet { session: Session(1), network: network.try_into().unwrap() };
// we need the whole substrate key pair to sign the batch
let (substrate_pair, key_pair) = {
@@ -283,7 +286,12 @@ async fn validator_set_rotation() {
// provide a batch to complete the handover and retire the previous set
let mut block_hash = BlockHash([0; 32]);
OsRng.fill_bytes(&mut block_hash.0);
let batch = Batch { network, id: 0, block: block_hash, instructions: vec![] };
let batch = Batch {
network: network.try_into().unwrap(),
id: 0,
block: block_hash,
instructions: vec![],
};
publish_tx(
&serai,
&SeraiInInstructions::execute_batch(SignedBatch {