use crate::Network;
use crate::common::{Address, Amount, Calldata, QuoteHash, QuotePayment, U256};
use crate::contract::network_token::{self, NetworkToken};
use crate::contract::payment_vault::MAX_TRANSFERS_PER_TRANSACTION;
use crate::contract::payment_vault::handler::PaymentVaultHandler;
use crate::merkle_batch_payment::PoolCommitment;
use crate::utils::http_provider;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Network token contract error: {0}")]
NetworkTokenContract(#[from] network_token::Error),
#[error("Data payments contract error: {0}")]
DataPaymentsContract(#[from] crate::contract::payment_vault::error::Error),
}
pub fn approve_to_spend_tokens_calldata(
network: &Network,
spender: Address,
value: U256,
) -> (Calldata, Address) {
let provider = http_provider(network.rpc_url().clone());
let network_token = NetworkToken::new(*network.payment_token_address(), provider);
network_token.approve_calldata(spender, value)
}
pub fn transfer_tokens_calldata(
network: &Network,
receiver: Address,
amount: U256,
) -> (Calldata, Address) {
let provider = http_provider(network.rpc_url().clone());
let network_token = NetworkToken::new(*network.payment_token_address(), provider);
network_token.transfer_calldata(receiver, amount)
}
#[derive(Serialize, Deserialize)]
pub struct PayForQuotesCalldataReturnType {
pub batched_calldata_map: HashMap<Calldata, Vec<QuoteHash>>,
pub to: Address,
pub approve_spender: Address,
pub approve_amount: Amount,
}
pub fn pay_for_quotes_calldata<T: IntoIterator<Item = QuotePayment>>(
network: &Network,
payments: T,
) -> Result<PayForQuotesCalldataReturnType, Error> {
let payments: Vec<_> = payments.into_iter().collect();
let total_amount = payments.iter().map(|(_, _, amount)| amount).sum();
let approve_spender = *network.payment_vault_address();
let approve_amount = total_amount;
let provider = http_provider(network.rpc_url().clone());
let data_payments = PaymentVaultHandler::new(*network.payment_vault_address(), provider);
let chunks = payments.chunks(MAX_TRANSFERS_PER_TRANSACTION);
let mut calldata_map: HashMap<Calldata, Vec<QuoteHash>> = HashMap::new();
for batch in chunks {
let quote_payments = batch.to_vec();
let (calldata, _) = data_payments.pay_for_quotes_calldata(quote_payments.clone())?;
let quote_hashes = quote_payments.into_iter().map(|(qh, _, _)| qh).collect();
calldata_map.insert(calldata, quote_hashes);
}
Ok(PayForQuotesCalldataReturnType {
batched_calldata_map: calldata_map,
to: *data_payments.contract.address(),
approve_spender,
approve_amount,
})
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MerklePaymentCalldataReturn {
pub calldata: Calldata,
pub to: Address,
pub approve_spender: Address,
pub approve_amount: Amount,
pub depth: u8,
pub merkle_payment_timestamp: u64,
}
pub fn pay_for_merkle_tree_calldata(
network: &Network,
depth: u8,
pool_commitments: Vec<PoolCommitment>,
merkle_payment_timestamp: u64,
) -> Result<MerklePaymentCalldataReturn, Error> {
let vault_address = *network.payment_vault_address();
let provider = http_provider(network.rpc_url().clone());
let handler = PaymentVaultHandler::new(vault_address, provider);
let (calldata, to) =
handler.pay_for_merkle_tree_calldata(depth, pool_commitments, merkle_payment_timestamp)?;
Ok(MerklePaymentCalldataReturn {
calldata,
to,
approve_spender: vault_address,
approve_amount: Amount::MAX,
depth,
merkle_payment_timestamp,
})
}