Skip to content

Commit

Permalink
feat: snip-12 typed data parsing and hashing
Browse files Browse the repository at this point in the history
  • Loading branch information
xJonathanLEI committed Jan 2, 2025
1 parent de3fec7 commit 73cdb6b
Show file tree
Hide file tree
Showing 16 changed files with 3,046 additions and 18 deletions.
26 changes: 17 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,21 +95,23 @@ Examples can be found in the [examples folder](./examples):

7. [Encoding and decoding Cairo types](./examples/serde.rs)

8. [Batched JSON-RPC requests](./examples/batch.rs)
8. [Parse a SNIP-12 message and compute its hash](./examples/snip_12_json.rs)

9. [Call a contract view function](./examples/erc20_balance.rs)
9. [Batched JSON-RPC requests](./examples/batch.rs)

10. [Deploy an Argent X account to a pre-funded address](./examples/deploy_argent_account.rs)
10. [Call a contract view function](./examples/erc20_balance.rs)

11. [Inspect public key with Ledger](./examples/ledger_public_key.rs)
11. [Deploy an Argent X account to a pre-funded address](./examples/deploy_argent_account.rs)

12. [Deploy an OpenZeppelin account with Ledger](./examples/deploy_account_with_ledger.rs)
12. [Inspect public key with Ledger](./examples/ledger_public_key.rs)

13. [Transfer ERC20 tokens with Ledger](./examples/transfer_with_ledger.rs)
13. [Deploy an OpenZeppelin account with Ledger](./examples/deploy_account_with_ledger.rs)

14. [Parsing a JSON-RPC request on the server side](./examples/parse_jsonrpc_request.rs)
14. [Transfer ERC20 tokens with Ledger](./examples/transfer_with_ledger.rs)

15. [Inspecting a erased provider-specific error type](./examples/downcast_provider_error.rs)
15. [Parsing a JSON-RPC request on the server side](./examples/parse_jsonrpc_request.rs)

16. [Inspecting a erased provider-specific error type](./examples/downcast_provider_error.rs)

## License

Expand Down
44 changes: 44 additions & 0 deletions examples/snip_12_json.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use starknet::{core::types::TypedData, macros::felt};

fn main() {
let raw = r#"{
"types": {
"StarknetDomain": [
{ "name": "name", "type": "shortstring" },
{ "name": "version", "type": "shortstring" },
{ "name": "chainId", "type": "shortstring" },
{ "name": "revision", "type": "shortstring" }
],
"Example Message": [
{ "name": "Name", "type": "string" },
{ "name": "Some Array", "type": "u128*" },
{ "name": "Some Object", "type": "My Object" }
],
"My Object": [
{ "name": "Some Selector", "type": "selector" },
{ "name": "Some Contract Address", "type": "ContractAddress" }
]
},
"primaryType": "Example Message",
"domain": {
"name": "Starknet Example",
"version": "1",
"chainId": "SN_MAIN",
"revision": "1"
},
"message": {
"Name": "some name",
"Some Array": [1, 2, 3, 4],
"Some Object": {
"Some Selector": "transfer",
"Some Contract Address": "0x0123"
}
}
}"#;

let typed_data = serde_json::from_str::<TypedData>(raw).unwrap();
println!("SNIP-12 revision: {}", typed_data.revision());

let message_hash = typed_data.message_hash(felt!("0x1234")).unwrap();
println!("SNIP-12 hash: {:#064x}", message_hash);
}
4 changes: 3 additions & 1 deletion starknet-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ starknet-core-derive = { version = "0.1.0", path = "../starknet-core-derive" }
base64 = { version = "0.21.0", default-features = false, features = ["alloc"] }
crypto-bigint = { version = "0.5.1", default-features = false }
flate2 = { version = "1.0.25", optional = true }
foldhash = { version = "0.1.4", default-features = false }
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
indexmap = { version = "2.7.0", default-features = false, features = ["serde"] }
num-traits = { version = "0.2.19", default-features = false }
serde = { version = "1.0.160", default-features = false, features = ["derive"] }
serde_json = { version = "1.0.96", default-features = false, features = ["alloc", "raw_value"] }
Expand All @@ -42,7 +44,7 @@ wasm-bindgen-test = "0.3.34"

[features]
default = ["std"]
std = ["dep:flate2", "starknet-crypto/std", "starknet-types-core/std"]
std = ["dep:flate2", "starknet-crypto/std", "starknet-types-core/std", "indexmap/std"]
no_unknown_fields = []

[[bench]]
Expand Down
20 changes: 20 additions & 0 deletions starknet-core/src/codec.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use alloc::{boxed::Box, fmt::Formatter, format, string::*, vec::*};
use core::{fmt::Display, mem::MaybeUninit};
use starknet_crypto::{PedersenHasher, PoseidonHasher};

use num_traits::ToPrimitive;

Expand Down Expand Up @@ -117,12 +118,31 @@ pub struct Error {
repr: Box<str>,
}

// This implementation is useful for encoding single-felt types.
impl FeltWriter for Felt {
fn write(&mut self, felt: Felt) {
*self = felt;
}
}

impl FeltWriter for Vec<Felt> {
fn write(&mut self, felt: Felt) {
self.push(felt);
}
}

impl FeltWriter for PedersenHasher {
fn write(&mut self, felt: Felt) {
self.update(felt);
}
}

impl FeltWriter for PoseidonHasher {
fn write(&mut self, felt: Felt) {
self.update(felt);
}
}

impl Encode for Felt {
fn encode<W: FeltWriter>(&self, writer: &mut W) -> Result<(), Error> {
writer.write(*self);
Expand Down
4 changes: 4 additions & 0 deletions starknet-core/src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ mod conversions;

mod serde_impls;

/// SNIP-12 typed data.
pub mod typed_data;
pub use typed_data::TypedData;

// TODO: better namespacing of exports?
mod codegen;
pub use codegen::{
Expand Down
Loading

0 comments on commit 73cdb6b

Please sign in to comment.