wasm_utils/proof/
ext_data.rs

1use ark_bn254::Fr as Bn254Fr;
2use ark_ff::{BigInteger, PrimeField};
3use ethabi::{encode, Token};
4use js_sys::{JsString, Uint8Array};
5use parity_scale_codec::{Decode, Encode};
6use tiny_keccak::{Hasher, Keccak};
7use wasm_bindgen::prelude::*;
8use wasm_bindgen::JsValue;
9
10#[derive(Encode, Decode, Default)]
11#[wasm_bindgen]
12pub struct ExtData {
13	#[wasm_bindgen(skip)]
14	pub recipient: Vec<u8>,
15	#[wasm_bindgen(skip)]
16	pub relayer: Vec<u8>,
17	#[wasm_bindgen(skip)]
18	pub ext_amount: i128,
19	#[wasm_bindgen(skip)]
20	pub fee: u128,
21	#[wasm_bindgen(skip)]
22	pub refund: u128,
23	#[wasm_bindgen(skip)]
24	pub token: Vec<u8>,
25	#[wasm_bindgen(skip)]
26	pub encrypted_output1: Vec<u8>,
27	#[wasm_bindgen(skip)]
28	pub encrypted_output2: Vec<u8>,
29}
30#[wasm_bindgen]
31impl ExtData {
32	#[wasm_bindgen(constructor)]
33	#[allow(clippy::too_many_arguments)]
34	pub fn new(
35		recipient: Uint8Array,
36		relayer: Uint8Array,
37		ext_amount: JsString,
38		fee: JsString,
39		refund: JsString,
40		token: Uint8Array,
41		encrypted_output1: Uint8Array,
42		encrypted_output2: Uint8Array,
43	) -> ExtData {
44		let fee: u128 = JsValue::from(fee).as_string().unwrap().parse().unwrap();
45		let ext_amount: i128 = JsValue::from(ext_amount).as_string().unwrap().parse().unwrap();
46		let recipient = recipient.to_vec();
47		let relayer = relayer.to_vec();
48		let refund: u128 = JsValue::from(refund).as_string().unwrap().parse().unwrap();
49		let token = token.to_vec();
50		let encrypted_output1 = encrypted_output1.to_vec();
51		let encrypted_output2 = encrypted_output2.to_vec();
52		ExtData {
53			fee,
54			ext_amount,
55			recipient,
56			relayer,
57			refund,
58			token,
59			encrypted_output1,
60			encrypted_output2,
61		}
62	}
63
64	pub fn get_encode(&self) -> Uint8Array {
65		let codec = self.encode_abi();
66		let mut keccak = Keccak::v256();
67		keccak.update(codec.as_slice());
68		let mut output = [0u8; 32];
69		keccak.finalize(&mut output);
70		let field_res = Bn254Fr::from_le_bytes_mod_order(&output);
71		let value = field_res.into_repr().to_bytes_le();
72
73		Uint8Array::from(value.as_slice())
74	}
75}
76#[allow(clippy::wrong_self_convention)]
77pub trait IntoAbiToken {
78	fn into_abi(&self) -> Token;
79	fn encode_abi(&self) -> Vec<u8> {
80		let token = self.into_abi();
81		encode(&[token])
82	}
83}
84
85impl IntoAbiToken for i128 {
86	fn into_abi(&self) -> Token {
87		let bytes = self.encode();
88		let mut bytes32: [u8; 32] = [0; 32];
89		for (i, byte) in bytes.iter().enumerate() {
90			bytes32[i] = *byte;
91		}
92		Token::Int(bytes32.into())
93	}
94}
95
96impl IntoAbiToken for u128 {
97	fn into_abi(&self) -> Token {
98		let bytes = self.encode();
99		let mut bytes32: [u8; 32] = [0; 32];
100		for (i, byte) in bytes.iter().enumerate() {
101			bytes32[i] = *byte;
102		}
103		Token::Uint(bytes32.into())
104	}
105}
106
107impl IntoAbiToken for [u8; 32] {
108	fn into_abi(&self) -> Token {
109		Token::Bytes(self.to_vec())
110	}
111}
112
113impl IntoAbiToken for ExtData {
114	fn into_abi(&self) -> Token {
115		// TODO: Make sure the encodings match the solidity side
116		let recipient = Token::Bytes(self.recipient.clone());
117		let ext_amount = Token::Bytes(self.ext_amount.encode());
118		let relayer = Token::Bytes(self.relayer.clone());
119		let fee = Token::Bytes(self.fee.encode());
120		let refund = Token::Bytes(self.refund.encode());
121		let token = Token::Bytes(self.token.clone());
122		let encrypted_output1 = Token::Bytes(self.encrypted_output1.clone());
123		let encrypted_output2 = Token::Bytes(self.encrypted_output2.clone());
124		let ext_data_args = vec![
125			recipient,
126			relayer,
127			ext_amount,
128			fee,
129			refund,
130			token,
131			encrypted_output1,
132			encrypted_output2,
133		];
134		Token::Tuple(ext_data_args)
135	}
136}