sendfun_sdk/utils/
creator_hash.rs1use solana_address::Address;
2
3#[must_use]
7pub fn creator_hash_from_id(
8 creator_platform: &str,
9 creator_id: &str,
10) -> Address {
11 let platform_len = (creator_platform.len() as u32).to_le_bytes();
12 let id_len = (creator_id.len() as u32).to_le_bytes();
13 Address::new_from_array(
14 solana_sha256_hasher::hashv(&[
15 &platform_len,
16 creator_platform.as_bytes(),
17 &id_len,
18 creator_id.as_bytes(),
19 ])
20 .to_bytes(),
21 )
22}
23
24#[must_use]
27pub fn encode_creator_id<const N: usize>(text: &str) -> Option<[u8; N]> {
28 let bytes = text.as_bytes();
29 let mut out = [0u8; N];
30 out.get_mut(..bytes.len())?.copy_from_slice(bytes);
31 Some(out)
32}
33
34#[must_use]
37pub fn decode_creator_id(bytes: &[u8]) -> Option<&str> {
38 let end = match bytes.iter().rposition(|&b| b != 0) {
39 Some(last) => last.checked_add(1)?,
40 None => 0,
41 };
42 core::str::from_utf8(bytes.get(..end)?).ok()
43}
44
45#[cfg(test)]
46mod tests {
47 use solana_address::{Address, address};
48
49 use super::creator_hash_from_id;
50
51 #[test]
52 fn creator_hash_wallet_platform() {
53 let hash =
54 creator_hash_from_id("wallet", "11111111111111111111111111111111");
55 let hash2 =
56 creator_hash_from_id("wallet", "11111111111111111111111111111111");
57 assert_eq!(hash, hash2);
58 let hash3 =
59 creator_hash_from_id("wallet", "22222222222222222222222222222222");
60 assert_ne!(hash, hash3);
61 }
62
63 #[test]
64 fn creator_hash_different_platforms() {
65 let hash_wallet = creator_hash_from_id("wallet", "test_id");
66 let hash_twitter = creator_hash_from_id("twitter", "test_id");
67 assert_ne!(hash_wallet, hash_twitter);
68 }
69
70 #[test]
71 fn creator_hash_matches_sha256() {
72 use sha2::{Digest, Sha256};
73
74 let platform = "wallet";
75 let id = "TestWalletAddress123456789012345";
76 let hash = creator_hash_from_id(platform, id);
77
78 let mut hasher = Sha256::new();
79 hasher.update((platform.len() as u32).to_le_bytes());
80 hasher.update(platform.as_bytes());
81 hasher.update((id.len() as u32).to_le_bytes());
82 hasher.update(id.as_bytes());
83 let expected = Address::new_from_array(hasher.finalize().into());
84 assert_eq!(hash, expected);
85 }
86
87 #[test]
88 fn creator_hash_matches_the_typescript_sdk() {
89 assert_eq!(
90 creator_hash_from_id("twitter", "alice123"),
91 address!("oiZL4KcM2jYpYBHDtTUm9QbGUeWvEfPQN35ufpDzxTL"),
92 );
93 }
94}