2024-09-18 00:54:20 -04:00
|
|
|
use alloy_core::primitives::U256;
|
2024-09-14 07:54:18 -04:00
|
|
|
|
2024-09-18 00:54:20 -04:00
|
|
|
use serai_client::primitives::{NetworkId, Coin, Balance};
|
2024-09-14 07:54:18 -04:00
|
|
|
|
|
|
|
|
use primitives::Payment;
|
|
|
|
|
use scanner::{KeyFor, AddressFor, EventualityFor};
|
|
|
|
|
|
2024-09-18 00:54:20 -04:00
|
|
|
use ethereum_schnorr::PublicKey;
|
|
|
|
|
use ethereum_router::Coin as EthereumCoin;
|
|
|
|
|
|
|
|
|
|
use crate::{DAI, transaction::Action, rpc::Rpc};
|
|
|
|
|
|
|
|
|
|
fn coin_to_ethereum_coin(coin: Coin) -> EthereumCoin {
|
|
|
|
|
assert_eq!(coin.network(), NetworkId::Ethereum);
|
|
|
|
|
match coin {
|
|
|
|
|
Coin::Ether => EthereumCoin::Ether,
|
|
|
|
|
Coin::Dai => EthereumCoin::Erc20(DAI),
|
|
|
|
|
_ => unreachable!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-14 07:54:18 -04:00
|
|
|
|
|
|
|
|
fn balance_to_ethereum_amount(balance: Balance) -> U256 {
|
|
|
|
|
assert_eq!(balance.coin.network(), NetworkId::Ethereum);
|
|
|
|
|
assert_eq!(balance.coin.decimals(), 8);
|
|
|
|
|
// Restore 10 decimals so we go from 8 decimals to 18 decimals
|
|
|
|
|
// TODO: Document the expectation all integrated coins have 18 decimals
|
|
|
|
|
let factor = U256::from(10_000_000_000u64);
|
|
|
|
|
U256::from(balance.amount.0) * factor
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub(crate) struct SmartContract {
|
|
|
|
|
pub(crate) chain_id: U256,
|
|
|
|
|
}
|
|
|
|
|
impl smart_contract_scheduler::SmartContract<Rpc> for SmartContract {
|
2024-09-18 00:54:20 -04:00
|
|
|
type SignableTransaction = Action;
|
2024-09-14 07:54:18 -04:00
|
|
|
|
|
|
|
|
fn rotate(
|
|
|
|
|
&self,
|
|
|
|
|
nonce: u64,
|
|
|
|
|
retiring_key: KeyFor<Rpc>,
|
|
|
|
|
new_key: KeyFor<Rpc>,
|
|
|
|
|
) -> (Self::SignableTransaction, EventualityFor<Rpc>) {
|
2024-09-18 00:54:20 -04:00
|
|
|
let action = Action::SetKey {
|
2024-09-14 07:54:18 -04:00
|
|
|
chain_id: self.chain_id,
|
2024-09-18 00:54:20 -04:00
|
|
|
nonce,
|
2024-09-14 07:54:18 -04:00
|
|
|
key: PublicKey::new(new_key).expect("rotating to an invald key"),
|
|
|
|
|
};
|
2024-09-18 00:54:20 -04:00
|
|
|
(action.clone(), action.eventuality())
|
2024-09-14 07:54:18 -04:00
|
|
|
}
|
2024-09-18 00:54:20 -04:00
|
|
|
|
2024-09-14 07:54:18 -04:00
|
|
|
fn fulfill(
|
|
|
|
|
&self,
|
|
|
|
|
nonce: u64,
|
|
|
|
|
key: KeyFor<Rpc>,
|
|
|
|
|
payments: Vec<Payment<AddressFor<Rpc>>>,
|
|
|
|
|
) -> Vec<(Self::SignableTransaction, EventualityFor<Rpc>)> {
|
|
|
|
|
let mut outs = Vec::with_capacity(payments.len());
|
|
|
|
|
for payment in payments {
|
2024-09-18 00:54:20 -04:00
|
|
|
outs.push((
|
|
|
|
|
payment.address().clone(),
|
|
|
|
|
(
|
|
|
|
|
coin_to_ethereum_coin(payment.balance().coin),
|
|
|
|
|
balance_to_ethereum_amount(payment.balance()),
|
|
|
|
|
),
|
|
|
|
|
));
|
2024-09-14 07:54:18 -04:00
|
|
|
}
|
|
|
|
|
|
2024-09-18 00:54:20 -04:00
|
|
|
// TODO: Per-batch gas limit
|
|
|
|
|
// TODO: Create several batches
|
2024-09-18 15:50:21 -04:00
|
|
|
// TODO: Handle fees
|
2024-09-18 00:54:20 -04:00
|
|
|
let action = Action::Batch { chain_id: self.chain_id, nonce, outs };
|
2024-09-14 07:54:18 -04:00
|
|
|
|
2024-09-18 00:54:20 -04:00
|
|
|
vec![(action.clone(), action.eventuality())]
|
2024-09-14 07:54:18 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) type Scheduler = smart_contract_scheduler::Scheduler<Rpc, SmartContract>;
|