| Crates.io | tap-ivms101 |
| lib.rs | tap-ivms101 |
| version | 0.4.0 |
| created_at | 2025-06-17 07:34:45.312002+00 |
| updated_at | 2025-06-17 07:34:45.312002+00 |
| description | IVMS 101.2023 data model implementation for the Travel Asset Protocol |
| homepage | |
| repository | https://github.com/TransactionAuthorizationProtocol/tap-rs |
| max_upload_size | |
| id | 1715370 |
| size | 133,507 |
A complete implementation of the IVMS 101.2023 data model for the Travel Asset Protocol (TAP).
This crate provides a comprehensive implementation of the interVASP Messaging Standard (IVMS) 101.2023, which is used for Travel Rule compliance in virtual asset transfers. IVMS 101 is the global standard for exchanging required originator and beneficiary information between Virtual Asset Service Providers (VASPs) to comply with FATF Recommendation 16.
Add to your Cargo.toml:
[dependencies]
tap-ivms101 = "0.1.0"
use tap_ivms101::builder::*;
use tap_ivms101::types::*;
use tap_ivms101::message::*;
// Create a natural person
let person_name = NaturalPersonNameBuilder::new()
.legal_name("Smith", "John")
.build()?;
let person = NaturalPersonBuilder::new()
.name(person_name)
.country_of_residence("US")
.national_id(
"123456789",
NationalIdentifierType::NationalIdentityNumber,
"US"
)
.build()?;
// Create a legal person (VASP)
let vasp_name = LegalPersonNameBuilder::new()
.legal_name("Example Exchange Ltd.")
.build()?;
let vasp = LegalPersonBuilder::new()
.name(vasp_name)
.lei("529900HNOAA1KXQJUQ27")?
.country_of_registration("US")
.build()?;
// Create an IVMS message
let message = IvmsMessageBuilder::new()
.originator(vec![Person::NaturalPerson(person)])
.beneficiary(vec![Person::NaturalPerson(person.clone())])
.originating_vasp(Person::LegalPerson(vasp))
.transaction(
"1000.00",
"USD",
TransactionDirection::Outgoing,
"tx-123456",
"2024-01-15T10:30:00Z"
)?
.build()?;
// Serialize to JSON
let json = message.to_json_pretty()?;
use tap_ivms101::builder::*;
use tap_ivms101::types::*;
let address = GeographicAddressBuilder::new()
.address_type(AddressType::Home)
.street_name("123 Main Street")
.building_number("123")
.post_code("12345")
.town_name("New York")
.country("US")
.build()?;
let person = NaturalPersonBuilder::new()
.name(/* ... */)
.add_address(address)
.build()?;
All data structures include comprehensive validation to ensure compliance:
use tap_ivms101::validation::*;
// Validate country codes (ISO 3166)
validate_country_code("US")?; // OK
validate_country_code("USA")?; // Error: must be 2 characters
validate_country_code("XX")?; // Error: invalid country code
// Validate currency codes (ISO 4217)
validate_currency_code("USD")?; // OK
validate_currency_code("EUR")?; // OK
validate_currency_code("USDT")?; // Error: not ISO 4217
// Validate LEI (Legal Entity Identifier)
validate_lei("529900HNOAA1KXQJUQ27")?; // OK
validate_lei("INVALID")?; // Error: must be 20 characters
// Validate BIC/SWIFT codes
validate_bic("DEUTDEFF")?; // OK (8 chars)
validate_bic("DEUTDEFFXXX")?; // OK (11 chars)
validate_bic("INVALID")?; // Error: wrong length
// Validate required fields
let person = NaturalPersonBuilder::new()
.build(); // Error: missing required name field
This implementation follows the IVMS 101.2023 specification, ensuring full compliance with Travel Rule requirements:
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
This crate is designed to work seamlessly with the Travel Asset Protocol (TAP) ecosystem:
use tap_ivms101::message::IvmsMessage;
use tap_msg::message::transfer::Transfer;
// Create IVMS data for a TAP transfer
let ivms_data = IvmsMessageBuilder::new()
// ... build IVMS message
.build()?;
// Attach to TAP transfer message
let transfer = Transfer {
// ... other fields
ivms101: Some(ivms_data.to_json()?),
};
The crate provides detailed error messages for validation failures:
use tap_ivms101::error::IvmsError;
match result {
Err(IvmsError::ValidationError(msg)) => {
// Handle validation error
eprintln!("Validation failed: {}", msg);
}
Err(IvmsError::SerializationError(e)) => {
// Handle JSON error
eprintln!("Serialization failed: {}", e);
}
_ => {}
}