Transfer

Transfer

The Transfer standard allows the sending of SCL tokens. This can be done either through a single transfer command or through a batched transfer command (where multiple tokens can be sent at the cost of one transaction fee).


Create Transfer

Commands

[UTXO_SENDER_1, UTXO_SENDER_2, ... , UTXO_SENDER_N] is the list of UTXOs which send the tokens. [UTXO_RECEIVER_1(AMOUNT), UTXO_RECEIVER_2(AMOUNT), ... , CHANGE_UTXO(AMOUNT)] is the list of UTXOs which receive the tokens. The CHANGE_UTXO is the last UTXO.

Single Transfer

<TXID,
    {CONTRACT_ID_1:TRANSFER[
        [UTXO_SENDER_1, UTXO_SENDER_2, ... , UTXO_SENDER_N],
        [UTXO_RECEIVER_1(AMOUNT), UTXO_RECEIVER_2(AMOUNT), ... , CHANGE_UTXO(AMOUNT)]]}>

Batched Transfer

<TXID,
    {CONTRACT_ID_1:TRANSFER[
        [UTXO_SENDER_1, UTXO_SENDER_2, ... , UTXO_SENDER_N],
        [UTXO_RECEIVER_1(AMOUNT), UTXO_RECEIVER_2(AMOUNT), ... , CHANGE_UTXO(AMOUNT)]]}>
    {CONTRACT_ID_2:TRANSFER[
        [UTXO_SENDER_1, UTXO_SENDER_2, ... , UTXO_SENDER_N],
        [UTXO_RECEIVER_1(AMOUNT), UTXO_RECEIVER_2(AMOUNT), ... , CHANGE_UTXO(AMOUNT)]]},
    ...,
    {CONTRACT_ID_N:TRANSFER[
        [UTXO_SENDER_1, UTXO_SENDER_2, ... , UTXO_SENDER_N],
        [UTXO_RECEIVER_1(AMOUNT), UTXO_RECEIVER_2(AMOUNT), ... , CHANGE_UTXO(AMOUNT)]]}>

x

Examples

Single Transfer

<df8125d5302213844221fc97660e7b538f55155a48577f33b09a86d2808ca848,
    {50b7fc619f858f5bf7d12b392a2b26489ef11d4d62c3d182d0754f3df9bbebf4:TRANSFER[
        [494afb28cd5de10ab76394ccaf18f6f2ee7e4fe0d8c19ad04fc4b40e63f7be92:23,a3e71f146c17db792d12e24a25957a0fe7baebfc40b0bf3a9bb1d52f8ce9844b:23],
        [TXID:0(42000000000),TXID:2(818000000000)]]}

Batched Transfer

[!NOTE] Coming soon!

Implementations

Rust

pub fn transfer(&mut self, txid: &String, payload: &String, sender_utxos: &Vec<String>, receivers: &Vec<(String, u64)>, current_block_height: u64) -> Result<(Vec<bool>, u64), String> {
    let mut owners_amount: u64 = 0;
    for sender_utxo in sender_utxos.clone() {
        if self.owners.contains_key(&sender_utxo) {
            owners_amount += self.owners[&sender_utxo];
        }
    }
    if owners_amount == 0 {
        return Err("transfer: owner amount is zero".to_string());
    }
    let mut total_value: u64 = 0;
    for entry in receivers.clone() {
        total_value += entry.1;
    }

    let mut drips = match self.drips.clone() {
        Some(drips) => drips,
        None => HashMap::new(),
    };

    if total_value <= owners_amount {
        let mut new_drips: Vec<Drip> = Vec::new();
        for sender_utxo in sender_utxos.clone() {
            if self.owners.contains_key(&sender_utxo.clone()) {
                self.owners.remove(&sender_utxo);
                if let Some(old_drips) = drips.get(&sender_utxo) {
                    for drip in old_drips {
                        let new_drip = Drip {
                            block_end: drip.block_end.clone(),
                            drip_amount: drip.drip_amount.clone(),
                            amount: drip.amount.clone() - (current_block_height - drip.start_block) * drip.drip_amount,
                            start_block: current_block_height,
                            last_block_dripped: current_block_height
                        };

                        new_drips.push(new_drip.clone());
                    }
                    
                    // Remove the old drip from the vector
                    drips.remove(&sender_utxo);
                }
            }
        }

        let last_index = receivers.len() - 1;
        let mut drip_ret = 0;
        if !new_drips.is_empty() {
            let last_receiver = &receivers[last_index].0.clone();       
            drips.insert(last_receiver.clone(), new_drips);
            let blocks_dripped = owners_amount - total_value;
        
            if let Some(owned) = self.owners.get_mut(last_receiver) {
                *owned += blocks_dripped;
                drip_ret = *owned;
            }
        }
        
        

        let mut recievers_drips_present: Vec<bool> = Vec::new(); 
        for entry in receivers.clone() {
            match self.owners.get(&entry.0) {
                Some(&e) => self.owners.insert(entry.0.clone(), &e + entry.1),
                None => self.owners.insert(entry.0.clone(), entry.1)
            };

            if drips.contains_key(&entry.0) {
                recievers_drips_present.push(true);
            }else{
                recievers_drips_present.push(false);
            }
        }

        self.payloads.insert(txid.to_string(), payload.to_string());
        self.drips = Some(drips);
        return Ok((recievers_drips_present, drip_ret));
    } else{
        return Err("transfer: owner amount is less than recievers total".to_string());
    }
}