bluefin-pro 1.13.0

Software Development Kit for Bluefin Pro
Documentation
use crate::core::PrivateKey;
use crate::signature::{self, Result};
use bluefin_api::models::WithdrawRequest;
use sui_sdk_types::SignatureScheme;

use crate::signature::RequestExt;

impl RequestExt for WithdrawRequest {
    fn sign(self, private_key: PrivateKey, scheme: SignatureScheme) -> Result<Self> {
        let converted = signature::conversion::signable::WithdrawRequest::from(self.clone());

        let signature = signature::signature(converted, private_key, scheme)?;
        Ok(WithdrawRequest { signature, ..self })
    }

    fn compute_hash(self) -> Result<String> {
        let converted = signature::conversion::hashable::WithdrawRequest::try_from(self.clone())?;
        signature::compute_hash(&converted)
    }
}

#[cfg(test)]
mod tests {
    use bluefin_api::models::{WithdrawRequest, WithdrawRequestSignedFields};
    use rand::rngs::OsRng;
    use sui_crypto::ed25519::Ed25519VerifyingKey;
    use sui_crypto::secp256k1::Secp256k1VerifyingKey;
    use sui_sdk_types::{Ed25519PublicKey, Secp256k1PublicKey, SignatureScheme};

    use crate::signature::RequestExt;
    use crate::signature::{self, testing::verify_signature};

    fn verify_request_signature(request: &WithdrawRequest, signer_address: &str) {
        assert!(!request.signature.is_empty());

        match verify_signature(
            signer_address,
            &request.signature.clone(),
            request.clone(),
            signature::conversion::signable::WithdrawRequest::from,
        ) {
            Ok(()) => {}
            Err(e) => panic!("{e}"),
        }
    }

    #[test]
    fn sign_request_is_successful_ed25519() {
        let private_key = ed25519_dalek::SigningKey::generate(&mut OsRng);
        let signer_address = Ed25519VerifyingKey::new(&Ed25519PublicKey::new(
            private_key.verifying_key().to_bytes(),
        ))
        .unwrap()
        .public_key()
        .derive_address()
        .to_hex();
        let request = withdraw_request()
            .sign(private_key.to_bytes(), SignatureScheme::Ed25519)
            .unwrap();
        verify_request_signature(&request, &signer_address);
    }

    #[test]
    fn sign_request_is_successful_secp256k1() {
        let private_key = secp256k1::SecretKey::new(&mut OsRng);
        let secp = secp256k1::Secp256k1::new();
        let signer_address = Secp256k1VerifyingKey::new(&Secp256k1PublicKey::new(
            private_key.public_key(&secp).serialize(),
        ))
        .unwrap()
        .public_key()
        .derive_address()
        .to_hex();

        let request = withdraw_request()
            .sign(private_key.secret_bytes(), SignatureScheme::Secp256k1)
            .unwrap();
        verify_request_signature(&request, &signer_address);
    }

    #[test]
    fn compute_hash_is_successful() {
        let request = withdraw_request();
        let hash = request.compute_hash().unwrap();
        assert!(!hash.is_empty());
    }

    fn withdraw_request() -> WithdrawRequest {
        WithdrawRequest {
            signed_fields: WithdrawRequestSignedFields {
                asset_symbol: "USDC".to_string(),
                account_address:
                    "0x8e78225d72b1d7b1f63e5e9f88f09b12ca66c84e2fc8b91fc10f6a0c51230615".into(),
                amount_e9: "3500000000000".to_string(),
                salt: "1725930601205".to_string(),
                eds_id: "0x8e78225d72b1d7b1f63e5e9f88f09b12ca66c84e2fc8b91fc10f6a0c51230615".into(),
                signed_at_millis: 1_725_931_543_867,
            },
            ..WithdrawRequest::default()
        }
    }
}