pub const ARKM_CLIENT_KEY: &str = "gh67j345kl6hj5k432";
#[must_use]
pub fn sign_payload(path: &str, timestamp: &str) -> String {
sign_payload_with_key(path, timestamp, ARKM_CLIENT_KEY)
}
#[must_use]
pub fn sign_payload_with_key(path: &str, timestamp: &str, key: &str) -> String {
use sha2::{Digest, Sha256};
let inner = {
let mut h = Sha256::new();
h.update(path.as_bytes());
h.update(b":");
h.update(timestamp.as_bytes());
h.update(b":");
h.update(key.as_bytes());
hex::encode(h.finalize())
};
let mut h = Sha256::new();
h.update(key.as_bytes());
h.update(b":");
h.update(inner.as_bytes());
hex::encode(h.finalize())
}
#[cfg(test)]
mod tests {
use super::*;
const HAR_FIXTURES: &[(&str, &str, &str)] = &[
(
"/user",
"1777514565",
"e40dd6181c5901ae5acc014ff893808877118520c33927645b51b438ff1e700e",
),
(
"/marketdata/geckoterminal/get_dex_pool_data",
"1777514565",
"fdb638263c4da2b605639a1d7b585842a5bbd00d57d477ec1e5372686473da12",
),
(
"/user/entities//is_not_viewable",
"1777514565",
"6a677376b5d508076056e4156d9e3ee40f8da62f40c463d13d2c832542f59032",
),
(
"/loans/address/0x971435fc38eed5e0aaff0dd717d0d16a02a4110e",
"1777514566",
"a168022e4def0b8ef68e801e30006c56ca0a7a35e9dfda2d8ebfd2615cc15af4",
),
(
"/transfers",
"1777514576",
"4b1a20d87aa128f631ee1bf94f388c145f784b443f1f5e9ff802c14b50568a83",
),
];
#[test]
fn sign_payload_matches_live_har_fixtures() {
for (path, ts, expected) in HAR_FIXTURES {
let got = sign_payload(path, ts);
assert_eq!(
&got, expected,
"signature mismatch for path={path:?} ts={ts}: got {got}, expected {expected}"
);
}
}
#[test]
fn sign_payload_returns_64_hex_chars() {
let p = sign_payload("/anything", "1234567890");
assert_eq!(p.len(), 64);
assert!(p.chars().all(|c| c.is_ascii_hexdigit()));
}
#[test]
fn sign_payload_changes_with_timestamp() {
let a = sign_payload("/user", "1700000000");
let b = sign_payload("/user", "1700000001");
assert_ne!(a, b);
}
}