Skip to content

Commit ab7ad26

Browse files
committed
cleanup
1 parent f8500a6 commit ab7ad26

File tree

4 files changed

+170
-150
lines changed

4 files changed

+170
-150
lines changed

src/eth.rs

Lines changed: 24 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,9 @@ pub use alloy::rpc::types::{
66
Block, BlockId, BlockNumberOrTag, FeeHistory, Filter, FilterBlockOption, Log, Transaction,
77
TransactionReceipt,
88
};
9-
use alloy_primitives::FixedBytes;
109
pub use alloy_primitives::{Address, BlockHash, BlockNumber, Bytes, TxHash, U128, U256, U64, U8};
11-
use alloy_sol_macro::sol;
12-
use alloy_sol_types::SolCall;
1310
use serde::{Deserialize, Serialize};
1411
use std::collections::{HashMap, HashSet};
15-
use std::str::FromStr;
1612

1713
//
1814
// types mirrored from runtime module
@@ -184,20 +180,6 @@ impl std::cmp::PartialEq<str> for NodeOrRpcUrl {
184180
}
185181
}
186182

187-
/// KiMap default address
188-
const KIMAP: &str = "0x0165878A594ca255338adfa4d48449f69242Eb8F";
189-
190-
// Sol structures for KiMap requests
191-
sol! {
192-
function get (
193-
bytes32 entryhash
194-
) external view returns (
195-
address tokenBoundAccount,
196-
address tokenOwner,
197-
bytes data
198-
);
199-
}
200-
201183
/// An EVM chain provider. Create this object to start making RPC calls.
202184
/// Set the chain_id to determine which chain to call: requests will fail
203185
/// unless the node this process is running on has access to a provider
@@ -572,14 +554,14 @@ impl Provider {
572554
self.send_request_and_parse_response::<Bytes>(action)
573555
}
574556

575-
/// Returns a KiMap instance with the default address using this provider.
576-
pub fn kimap(&self) -> KiMap {
577-
KiMap::default(self)
557+
/// Returns a Kimap instance with the default address using this provider.
558+
pub fn kimap(&self) -> crate::kimap::Kimap {
559+
crate::kimap::Kimap::default(self.request_timeout)
578560
}
579561

580-
/// Returns a KiMap instance with a custom address using this provider.
581-
pub fn kimap_with_address(&self, address: Address) -> KiMap {
582-
KiMap::new(self, address)
562+
/// Returns a Kimap instance with a custom address using this provider.
563+
pub fn kimap_with_address(self, address: Address) -> crate::kimap::Kimap {
564+
crate::kimap::Kimap::new(self, address)
583565
}
584566

585567
/// Sends a raw transaction to the network.
@@ -640,6 +622,24 @@ impl Provider {
640622
}
641623
}
642624

625+
/// Subscribe in a loop until successful
626+
pub fn subscribe_loop(&self, sub_id: u64, filter: Filter) {
627+
loop {
628+
match self.subscribe(sub_id, filter.clone()) {
629+
Ok(()) => break,
630+
Err(_) => {
631+
crate::print_to_terminal(
632+
0,
633+
"failed to subscribe to chain! trying again in 5s...",
634+
);
635+
std::thread::sleep(std::time::Duration::from_secs(5));
636+
continue;
637+
}
638+
}
639+
}
640+
crate::print_to_terminal(0, "subscribed to logs successfully");
641+
}
642+
643643
/// Unsubscribes from a previously created subscription.
644644
///
645645
/// # Parameters
@@ -666,64 +666,3 @@ impl Provider {
666666
}
667667
}
668668
}
669-
670-
/// Helper struct for the KiMap.
671-
pub struct KiMap<'a> {
672-
provider: &'a Provider,
673-
address: Address,
674-
}
675-
676-
impl<'a> KiMap<'a> {
677-
/// Creates a new KiMap instance with a specified address.
678-
///
679-
/// # Arguments
680-
/// * `provider` - A reference to the Provider.
681-
/// * `address` - The address of the KiMap contract.
682-
pub fn new(provider: &'a Provider, address: Address) -> Self {
683-
Self { provider, address }
684-
}
685-
686-
/// Creates a new KiMap instance with the default address.
687-
///
688-
/// # Arguments
689-
/// * `provider` - A reference to the Provider.
690-
pub fn default(provider: &'a Provider) -> Self {
691-
Self::new(provider, Self::default_address())
692-
}
693-
694-
/// Returns the default KiMap contract address.
695-
pub fn default_address() -> Address {
696-
Address::from_str(KIMAP).unwrap()
697-
}
698-
699-
/// Gets an entry from the KiMap.
700-
///
701-
/// # Parameters
702-
/// - `entryhash`: The entry to get from the KiMap.
703-
/// # Returns
704-
/// A `Result<(Address, Address, Option<Bytes>), EthError>` representing the TBA, owner, and value if the entry is a note.
705-
pub fn get(&self, entryhash: &str) -> Result<(Address, Address, Option<Bytes>), EthError> {
706-
let get_call = getCall {
707-
entryhash: FixedBytes::<32>::from_str(entryhash)
708-
.map_err(|_| EthError::InvalidParams)?,
709-
}
710-
.abi_encode();
711-
712-
let tx_req = TransactionRequest::default()
713-
.input(TransactionInput::new(get_call.into()))
714-
.to(self.address);
715-
716-
let res_bytes = self.provider.call(tx_req, None)?;
717-
718-
let res = getCall::abi_decode_returns(&res_bytes, false)
719-
.map_err(|_| EthError::RpcMalformedResponse)?;
720-
721-
let note_data = if res.data == Bytes::default() {
722-
None
723-
} else {
724-
Some(res.data)
725-
};
726-
727-
Ok((res.tokenBoundAccount, res.tokenOwner, note_data))
728-
}
729-
}

src/kimap.rs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
use crate::eth::*;
2+
use crate::kimap::contract::getCall;
3+
use alloy::rpc::types::request::{TransactionInput, TransactionRequest};
4+
use alloy::{hex, primitives::keccak256};
5+
use alloy_primitives::FixedBytes;
6+
use alloy_primitives::B256;
7+
use alloy_primitives::{Address, Bytes};
8+
use alloy_sol_types::SolCall;
9+
use alloy_sol_types::SolValue;
10+
use std::str::FromStr;
11+
12+
/// kimap deployment address on optimism
13+
pub const KIMAP_ADDRESS: &'static str = "0x7290Aa297818d0b9660B2871Bb87f85a3f9B4559";
14+
/// optimism chain id
15+
pub const KIMAP_CHAIN_ID: u64 = 10;
16+
/// first block of kimap deployment on optimism
17+
pub const KIMAP_FIRST_BLOCK: u64 = 114_923_786;
18+
/// the root hash of kimap, empty bytes32
19+
pub const KIMAP_ROOT_HASH: &'static str =
20+
"0x0000000000000000000000000000000000000000000000000000000000000000";
21+
22+
// Sol structures for Kimap requests
23+
pub mod contract {
24+
use alloy_sol_macro::sol;
25+
26+
sol! {
27+
event Mint(bytes32 indexed parenthash, bytes32 indexed childhash, bytes indexed labelhash, bytes name);
28+
event Note(bytes32 indexed nodehash, bytes32 indexed notehash, bytes indexed labelhash, bytes note, bytes data);
29+
30+
function get (
31+
bytes32 entryhash
32+
) external view returns (
33+
address tokenBoundAccount,
34+
address tokenOwner,
35+
bytes memory data
36+
);
37+
}
38+
}
39+
40+
pub fn namehash(name: &str) -> String {
41+
let mut node = B256::default();
42+
43+
let mut labels: Vec<&str> = name.split('.').collect();
44+
labels.reverse();
45+
46+
for label in labels.iter() {
47+
let l = keccak256(label);
48+
node = keccak256((node, l).abi_encode_packed());
49+
}
50+
format!("0x{}", hex::encode(node))
51+
}
52+
53+
/// Helper struct for the Kimap.
54+
pub struct Kimap {
55+
pub provider: Provider,
56+
address: Address,
57+
}
58+
59+
impl Kimap {
60+
/// Creates a new Kimap instance with a specified address.
61+
///
62+
/// # Arguments
63+
/// * `provider` - A reference to the Provider.
64+
/// * `address` - The address of the Kimap contract.
65+
pub fn new(provider: Provider, address: Address) -> Self {
66+
Self { provider, address }
67+
}
68+
69+
/// Creates a new Kimap instance with the default address and chain ID.
70+
pub fn default(timeout: u64) -> Self {
71+
let provider = Provider::new(KIMAP_CHAIN_ID, timeout);
72+
Self::new(provider, Address::from_str(KIMAP_ADDRESS).unwrap())
73+
}
74+
75+
/// Returns the in-use Kimap contract address.
76+
pub fn address(&self) -> &Address {
77+
&self.address
78+
}
79+
80+
/// Gets an entry from the Kimap by its string-formatted name.
81+
///
82+
/// # Parameters
83+
/// - `path`: The name-path to get from the Kimap.
84+
/// # Returns
85+
/// A `Result<(Address, Address, Option<Bytes>), EthError>` representing the TBA, owner,
86+
/// and value if the entry exists and is a note.
87+
pub fn get(&self, path: &str) -> Result<(Address, Address, Option<Bytes>), EthError> {
88+
let get_call = getCall {
89+
entryhash: FixedBytes::<32>::from_str(&namehash(path))
90+
.map_err(|_| EthError::InvalidParams)?,
91+
}
92+
.abi_encode();
93+
94+
let tx_req = TransactionRequest::default()
95+
.input(TransactionInput::new(get_call.into()))
96+
.to(self.address);
97+
98+
let res_bytes = self.provider.call(tx_req, None)?;
99+
100+
let res = getCall::abi_decode_returns(&res_bytes, false)
101+
.map_err(|_| EthError::RpcMalformedResponse)?;
102+
103+
let note_data = if res.data == Bytes::default() {
104+
None
105+
} else {
106+
Some(res.data)
107+
};
108+
109+
Ok((res.tokenBoundAccount, res.tokenOwner, note_data))
110+
}
111+
112+
/// Gets an entry from the Kimap by its hash.
113+
///
114+
/// # Parameters
115+
/// - `entryhash`: The entry to get from the Kimap.
116+
/// # Returns
117+
/// A `Result<(Address, Address, Option<Bytes>), EthError>` representing the TBA, owner,
118+
/// and value if the entry exists and is a note.
119+
pub fn get_hash(&self, entryhash: &str) -> Result<(Address, Address, Option<Bytes>), EthError> {
120+
let get_call = getCall {
121+
entryhash: FixedBytes::<32>::from_str(entryhash)
122+
.map_err(|_| EthError::InvalidParams)?,
123+
}
124+
.abi_encode();
125+
126+
let tx_req = TransactionRequest::default()
127+
.input(TransactionInput::new(get_call.into()))
128+
.to(self.address);
129+
130+
let res_bytes = self.provider.call(tx_req, None)?;
131+
132+
let res = getCall::abi_decode_returns(&res_bytes, false)
133+
.map_err(|_| EthError::RpcMalformedResponse)?;
134+
135+
let note_data = if res.data == Bytes::default() {
136+
None
137+
} else {
138+
Some(res.data)
139+
};
140+
141+
Ok((res.tokenBoundAccount, res.tokenOwner, note_data))
142+
}
143+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ pub mod http;
3737
/// be incompatible with WIT types in some cases, leading to annoying errors.
3838
/// Use only to interact with the kernel or runtime in certain ways.
3939
pub mod kernel_types;
40+
/// Interact with the kimap module
41+
pub mod kimap;
4042
/// Interact with the key_value module
4143
pub mod kv;
4244
/// Interact with the networking module

src/net.rs

Lines changed: 1 addition & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
use crate::{get_blob, println, Address, NodeId, Request, SendError};
2-
use alloy::{hex, primitives::keccak256};
3-
use alloy_primitives::B256;
4-
use alloy_sol_types::SolValue;
1+
use crate::{get_blob, Address, NodeId, Request, SendError};
52
use serde::{Deserialize, Serialize};
63
use std::collections::BTreeMap;
74

@@ -181,64 +178,3 @@ pub fn get_name(namehash: &str, timeout: Option<u64>) -> anyhow::Result<String>
181178
Err(anyhow::anyhow!("unexpected response: {:?}", response))
182179
}
183180
}
184-
185-
/// namehash... kimap style
186-
pub fn namehash(name: &str) -> String {
187-
let mut node = B256::default();
188-
189-
let mut labels: Vec<&str> = name.split('.').collect();
190-
labels.reverse();
191-
192-
for label in labels.iter() {
193-
let l = keccak256(label);
194-
node = keccak256((node, l).abi_encode_packed());
195-
}
196-
format!("0x{}", hex::encode(node))
197-
}
198-
199-
/// take a DNSwire-formatted node ID from chain and convert it to a String
200-
pub fn dnswire_decode(wire_format_bytes: &[u8]) -> Result<String, DnsDecodeError> {
201-
let mut i = 0;
202-
let mut result = Vec::new();
203-
204-
while i < wire_format_bytes.len() {
205-
let len = wire_format_bytes[i] as usize;
206-
if len == 0 {
207-
break;
208-
}
209-
let end = i + len + 1;
210-
let mut span = match wire_format_bytes.get(i + 1..end) {
211-
Some(span) => span.to_vec(),
212-
None => return Err(DnsDecodeError::FormatError),
213-
};
214-
span.push('.' as u8);
215-
result.push(span);
216-
i = end;
217-
}
218-
219-
let flat: Vec<_> = result.into_iter().flatten().collect();
220-
221-
let name = String::from_utf8(flat).map_err(|e| DnsDecodeError::Utf8Error(e))?;
222-
223-
// Remove the trailing '.' if it exists (it should always exist)
224-
if name.ends_with('.') {
225-
Ok(name[0..name.len() - 1].to_string())
226-
} else {
227-
Ok(name)
228-
}
229-
}
230-
231-
#[derive(Clone, Debug, thiserror::Error)]
232-
pub enum DnsDecodeError {
233-
Utf8Error(std::string::FromUtf8Error),
234-
FormatError,
235-
}
236-
237-
impl std::fmt::Display for DnsDecodeError {
238-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
239-
match self {
240-
DnsDecodeError::Utf8Error(e) => write!(f, "UTF-8 error: {}", e),
241-
DnsDecodeError::FormatError => write!(f, "Format error"),
242-
}
243-
}
244-
}

0 commit comments

Comments
 (0)