|
| 1 | +use candid::{Decode, Encode}; |
| 2 | +use serde::Serialize; |
| 3 | +use starknet::core::codec::{Decode as StarknetDecode, Encode as StarknetEncode}; |
| 4 | +use starknet_crypto::Felt; |
| 5 | + |
| 6 | +use crate::client::env::proxy::starknet::{ |
| 7 | + CallData, ContextStorageEntriesResponse, StarknetContextStorageEntriesRequest, |
| 8 | +}; |
| 9 | +use crate::client::env::Method; |
| 10 | +use crate::client::protocol::icp::Icp; |
| 11 | +use crate::client::protocol::near::Near; |
| 12 | +use crate::client::protocol::starknet::Starknet; |
| 13 | +use crate::types::ContextStorageEntry; |
| 14 | + |
| 15 | +#[derive(Clone, Debug, Serialize)] |
| 16 | +pub(super) struct ContextStorageEntriesRequest { |
| 17 | + pub(super) offset: usize, |
| 18 | + pub(super) limit: usize, |
| 19 | +} |
| 20 | + |
| 21 | +impl Method<Near> for ContextStorageEntriesRequest { |
| 22 | + const METHOD: &'static str = "context_storage_entries"; |
| 23 | + |
| 24 | + type Returns = Vec<ContextStorageEntry>; |
| 25 | + |
| 26 | + fn encode(self) -> eyre::Result<Vec<u8>> { |
| 27 | + serde_json::to_vec(&self).map_err(Into::into) |
| 28 | + } |
| 29 | + |
| 30 | + fn decode(response: Vec<u8>) -> eyre::Result<Self::Returns> { |
| 31 | + // Decode the response as Vec of tuples with boxed slices |
| 32 | + let entries: Vec<(Box<[u8]>, Box<[u8]>)> = serde_json::from_slice(&response) |
| 33 | + .map_err(|e| eyre::eyre!("Failed to decode response: {}", e))?; |
| 34 | + |
| 35 | + // Convert to ContextStorageEntry |
| 36 | + Ok(entries |
| 37 | + .into_iter() |
| 38 | + .map(|(key, value)| ContextStorageEntry { |
| 39 | + key: key.into(), |
| 40 | + value: value.into(), |
| 41 | + }) |
| 42 | + .collect()) |
| 43 | + } |
| 44 | +} |
| 45 | + |
| 46 | +impl Method<Starknet> for ContextStorageEntriesRequest { |
| 47 | + const METHOD: &'static str = "context_storage_entries"; |
| 48 | + |
| 49 | + type Returns = Vec<ContextStorageEntry>; |
| 50 | + |
| 51 | + fn encode(self) -> eyre::Result<Vec<u8>> { |
| 52 | + let req = StarknetContextStorageEntriesRequest { |
| 53 | + offset: Felt::from(self.offset as u64), |
| 54 | + length: Felt::from(self.limit as u64), |
| 55 | + }; |
| 56 | + let mut call_data = CallData::default(); |
| 57 | + req.encode(&mut call_data)?; |
| 58 | + Ok(call_data.0) |
| 59 | + } |
| 60 | + |
| 61 | + fn decode(response: Vec<u8>) -> eyre::Result<Self::Returns> { |
| 62 | + if response.is_empty() { |
| 63 | + return Ok(vec![]); |
| 64 | + } |
| 65 | + |
| 66 | + // Convert bytes to Felts |
| 67 | + let chunks = response.chunks_exact(32); |
| 68 | + let felts: Vec<Felt> = chunks |
| 69 | + .map(|chunk| { |
| 70 | + let chunk_array: [u8; 32] = chunk |
| 71 | + .try_into() |
| 72 | + .map_err(|e| eyre::eyre!("Failed to convert chunk to array: {}", e))?; |
| 73 | + Ok(Felt::from_bytes_be(&chunk_array)) |
| 74 | + }) |
| 75 | + .collect::<eyre::Result<Vec<Felt>>>()?; |
| 76 | + |
| 77 | + let response = ContextStorageEntriesResponse::decode_iter(&mut felts.iter())?; |
| 78 | + |
| 79 | + Ok(response.entries.into_iter().map(Into::into).collect()) |
| 80 | + } |
| 81 | +} |
| 82 | + |
| 83 | +impl Method<Icp> for ContextStorageEntriesRequest { |
| 84 | + const METHOD: &'static str = "context_storage_entries"; |
| 85 | + |
| 86 | + type Returns = Vec<ContextStorageEntry>; |
| 87 | + |
| 88 | + fn encode(self) -> eyre::Result<Vec<u8>> { |
| 89 | + // Encode offset and limit using Candid |
| 90 | + Encode!(&self.offset, &self.limit) |
| 91 | + .map_err(|e| eyre::eyre!("Failed to encode request: {}", e)) |
| 92 | + } |
| 93 | + |
| 94 | + fn decode(response: Vec<u8>) -> eyre::Result<Self::Returns> { |
| 95 | + // Decode the response as Vec of tuples |
| 96 | + let entries: Vec<(Vec<u8>, Vec<u8>)> = Decode!(&response, Vec<(Vec<u8>, Vec<u8>)>) |
| 97 | + .map_err(|e| eyre::eyre!("Failed to decode response: {}", e))?; |
| 98 | + |
| 99 | + // Convert to ContextStorageEntry |
| 100 | + Ok(entries |
| 101 | + .into_iter() |
| 102 | + .map(|(key, value)| ContextStorageEntry { key, value }) |
| 103 | + .collect()) |
| 104 | + } |
| 105 | +} |
0 commit comments