mirror of
https://github.com/status-im/status-react.git
synced 2025-01-24 18:00:45 +00:00
parent
3e7f7232fb
commit
00a503bf84
@ -1411,6 +1411,31 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||||||
return Statusgo.identicon(seed);
|
return Statusgo.identicon(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||||
|
public String encodeTransfer(final String to, final String value) {
|
||||||
|
return Statusgo.encodeTransfer(to, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||||
|
public String encodeFunctionCall(final String method, final String paramsJSON) {
|
||||||
|
return Statusgo.encodeFunctionCall(method, paramsJSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||||
|
public String decodeParameters(final String decodeParamJSON) {
|
||||||
|
return Statusgo.decodeParameters(decodeParamJSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||||
|
public String hexToNumber(final String hex) {
|
||||||
|
return Statusgo.hexToNumber(hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
||||||
|
public String numberToHex(final String numString) {
|
||||||
|
return Statusgo.numberToHex(numString);
|
||||||
|
}
|
||||||
|
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
public void identiconAsync(final String seed, final Callback callback) {
|
public void identiconAsync(final String seed, final Callback callback) {
|
||||||
Log.d(TAG, "identiconAsync");
|
Log.d(TAG, "identiconAsync");
|
||||||
@ -1572,5 +1597,6 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||||||
|
|
||||||
StatusThreadPoolExecutor.getInstance().execute(r);
|
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -820,6 +820,28 @@ RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(identicon:(NSString *)publicKey) {
|
|||||||
return StatusgoIdenticon(publicKey);
|
return StatusgoIdenticon(publicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(encodeTransfer:(NSString *)to
|
||||||
|
value:(NSString *)value) {
|
||||||
|
return StatusgoEncodeTransfer(to,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(encodeFunctionCall:(NSString *)method
|
||||||
|
paramsJSON:(NSString *)paramsJSON) {
|
||||||
|
return StatusgoEncodeFunctionCall(method,paramsJSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(decodeParameters:(NSString *)decodeParamJSON) {
|
||||||
|
return StatusgoDecodeParameters(decodeParamJSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(hexToNumber:(NSString *)hex) {
|
||||||
|
return StatusgoHexToNumber(hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(numberToHex:(NSString *)numString) {
|
||||||
|
return StatusgoNumberToHex(numString);
|
||||||
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(validateMnemonic:(NSString *)seed
|
RCT_EXPORT_METHOD(validateMnemonic:(NSString *)seed
|
||||||
callback:(RCTResponseSenderBlock)callback) {
|
callback:(RCTResponseSenderBlock)callback) {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
@ -386,6 +386,182 @@ void _Identicon(const FunctionCallbackInfo<Value>& args) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _EncodeTransfer(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Isolate* isolate = args.GetIsolate();
|
||||||
|
Local<Context> context = isolate->GetCurrentContext();
|
||||||
|
|
||||||
|
if (args.Length() != 2) {
|
||||||
|
// Throw an Error that is passed back to JavaScript
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for EncodeTransfer")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the argument types
|
||||||
|
|
||||||
|
if (!args[0]->IsString()) {
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'to'")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!args[1]->IsString()) {
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'value'")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
|
||||||
|
char *arg0 = *arg0Obj;
|
||||||
|
String::Utf8Value arg1Obj(isolate, args[1]->ToString(context).ToLocalChecked());
|
||||||
|
char *arg1 = *arg1Obj;
|
||||||
|
|
||||||
|
// Call exported Go function, which returns a C string
|
||||||
|
char *c = EncodeTransfer(arg0, arg1);
|
||||||
|
|
||||||
|
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
|
||||||
|
args.GetReturnValue().Set(ret);
|
||||||
|
delete c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _EncodeFunctionCall(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Isolate* isolate = args.GetIsolate();
|
||||||
|
Local<Context> context = isolate->GetCurrentContext();
|
||||||
|
|
||||||
|
if (args.Length() != 2) {
|
||||||
|
// Throw an Error that is passed back to JavaScript
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for EncodeFunctionCall")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the argument types
|
||||||
|
|
||||||
|
if (!args[0]->IsString()) {
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'method'")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!args[1]->IsString()) {
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'paramsJSON'")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
|
||||||
|
char *arg0 = *arg0Obj;
|
||||||
|
String::Utf8Value arg1Obj(isolate, args[1]->ToString(context).ToLocalChecked());
|
||||||
|
char *arg1 = *arg1Obj;
|
||||||
|
|
||||||
|
// Call exported Go function, which returns a C string
|
||||||
|
char *c = EncodeFunctionCall(arg0, arg1);
|
||||||
|
|
||||||
|
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
|
||||||
|
args.GetReturnValue().Set(ret);
|
||||||
|
delete c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _DecodeParameters(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Isolate* isolate = args.GetIsolate();
|
||||||
|
Local<Context> context = isolate->GetCurrentContext();
|
||||||
|
|
||||||
|
if (args.Length() != 1) {
|
||||||
|
// Throw an Error that is passed back to JavaScript
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for DecodeParameters")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the argument types
|
||||||
|
|
||||||
|
if (!args[0]->IsString()) {
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'decodeParamJSON'")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
|
||||||
|
char *arg0 = *arg0Obj;
|
||||||
|
|
||||||
|
// Call exported Go function, which returns a C string
|
||||||
|
char *c = DecodeParameters(arg0);
|
||||||
|
|
||||||
|
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
|
||||||
|
args.GetReturnValue().Set(ret);
|
||||||
|
delete c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _HexToNumber(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Isolate* isolate = args.GetIsolate();
|
||||||
|
Local<Context> context = isolate->GetCurrentContext();
|
||||||
|
|
||||||
|
if (args.Length() != 1) {
|
||||||
|
// Throw an Error that is passed back to JavaScript
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for HexToNumber")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the argument types
|
||||||
|
|
||||||
|
if (!args[0]->IsString()) {
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'hex'")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
|
||||||
|
char *arg0 = *arg0Obj;
|
||||||
|
|
||||||
|
// Call exported Go function, which returns a C string
|
||||||
|
char *c = HexToNumber(arg0);
|
||||||
|
|
||||||
|
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
|
||||||
|
args.GetReturnValue().Set(ret);
|
||||||
|
delete c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _NumberToHex(const FunctionCallbackInfo<Value>& args) {
|
||||||
|
Isolate* isolate = args.GetIsolate();
|
||||||
|
Local<Context> context = isolate->GetCurrentContext();
|
||||||
|
|
||||||
|
if (args.Length() != 1) {
|
||||||
|
// Throw an Error that is passed back to JavaScript
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong number of arguments for NumberToHex")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the argument types
|
||||||
|
|
||||||
|
if (!args[0]->IsString()) {
|
||||||
|
isolate->ThrowException(Exception::TypeError(
|
||||||
|
String::NewFromUtf8Literal(isolate, "Wrong argument type for 'numString'")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String::Utf8Value arg0Obj(isolate, args[0]->ToString(context).ToLocalChecked());
|
||||||
|
char *arg0 = *arg0Obj;
|
||||||
|
|
||||||
|
// Call exported Go function, which returns a C string
|
||||||
|
char *c = NumberToHex(arg0);
|
||||||
|
|
||||||
|
Local<String> ret = String::NewFromUtf8(isolate, c).ToLocalChecked();
|
||||||
|
args.GetReturnValue().Set(ret);
|
||||||
|
delete c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void _Logout(const FunctionCallbackInfo<Value>& args) {
|
void _Logout(const FunctionCallbackInfo<Value>& args) {
|
||||||
Isolate* isolate = args.GetIsolate();
|
Isolate* isolate = args.GetIsolate();
|
||||||
|
|
||||||
@ -1583,6 +1759,11 @@ void init(Local<Object> exports) {
|
|||||||
NODE_SET_METHOD(exports, "initKeystore", _InitKeystore);
|
NODE_SET_METHOD(exports, "initKeystore", _InitKeystore);
|
||||||
NODE_SET_METHOD(exports, "stopCPUProfiling", _StopCPUProfiling);
|
NODE_SET_METHOD(exports, "stopCPUProfiling", _StopCPUProfiling);
|
||||||
NODE_SET_METHOD(exports, "identicon", _Identicon);
|
NODE_SET_METHOD(exports, "identicon", _Identicon);
|
||||||
|
NODE_SET_METHOD(exports, "encodeTransfer", _EncodeTransfer);
|
||||||
|
NODE_SET_METHOD(exports, "encodeFunctionCall", _EncodeFunctionCall);
|
||||||
|
NODE_SET_METHOD(exports, "decodeParameters", _DecodeParameters);
|
||||||
|
NODE_SET_METHOD(exports, "hexToNumber", _HexToNumber);
|
||||||
|
NODE_SET_METHOD(exports, "numberToHex", _NumberToHex);
|
||||||
NODE_SET_METHOD(exports, "logout", _Logout);
|
NODE_SET_METHOD(exports, "logout", _Logout);
|
||||||
NODE_SET_METHOD(exports, "hashMessage", _HashMessage);
|
NODE_SET_METHOD(exports, "hashMessage", _HashMessage);
|
||||||
NODE_SET_METHOD(exports, "resetChainData", _ResetChainData);
|
NODE_SET_METHOD(exports, "resetChainData", _ResetChainData);
|
||||||
|
@ -1,396 +0,0 @@
|
|||||||
(ns status-im.ethereum.abi-spec
|
|
||||||
(:require ["web3-utils" :as utils]
|
|
||||||
[cljs.spec.alpha :as spec]
|
|
||||||
[clojure.string :as string]
|
|
||||||
[status-im.ethereum.core :as ethereum]))
|
|
||||||
|
|
||||||
;; Utility functions for encoding
|
|
||||||
|
|
||||||
(defn right-pad [x]
|
|
||||||
(let [len (count x)
|
|
||||||
to-pad (- 64 (mod len 64))]
|
|
||||||
(if (= 64 to-pad)
|
|
||||||
x
|
|
||||||
(.rightPad utils x (+ len to-pad)))))
|
|
||||||
|
|
||||||
(defn left-pad [x]
|
|
||||||
(let [len (count x)
|
|
||||||
to-pad (- 64 (mod len 64))]
|
|
||||||
(if (= 64 to-pad)
|
|
||||||
x
|
|
||||||
(.leftPad utils x (+ len to-pad)))))
|
|
||||||
|
|
||||||
(defn to-two-complement [x]
|
|
||||||
(when x
|
|
||||||
(subs (.toTwosComplement utils x) 2)))
|
|
||||||
|
|
||||||
(defn utf8-to-hex [x]
|
|
||||||
(when x
|
|
||||||
(subs (ethereum/utf8-to-hex x) 2)))
|
|
||||||
|
|
||||||
(defn hex-to-boolean [x]
|
|
||||||
(= x "0x0"))
|
|
||||||
|
|
||||||
(defn bytes-to-hex [x]
|
|
||||||
(when x
|
|
||||||
(subs (.bytesToHex utils x) 2)))
|
|
||||||
|
|
||||||
(defn number-to-hex [x]
|
|
||||||
(when x
|
|
||||||
(subs (.numberToHex utils x) 2)))
|
|
||||||
|
|
||||||
(defn hex-to-utf8 [x]
|
|
||||||
(ethereum/hex-to-utf8 (str "0x" x)))
|
|
||||||
|
|
||||||
(defn hex-to-number [x]
|
|
||||||
(when x
|
|
||||||
(let [hex-x (str "0x" x)]
|
|
||||||
(try
|
|
||||||
(.hexToNumber utils hex-x)
|
|
||||||
(catch :default _
|
|
||||||
(.hexToNumberString utils hex-x))))))
|
|
||||||
|
|
||||||
(defn is-hex? [value]
|
|
||||||
(when value
|
|
||||||
(string/starts-with? value "0x")))
|
|
||||||
|
|
||||||
;; Encoder for parsed abi spec
|
|
||||||
|
|
||||||
(defmulti enc :type)
|
|
||||||
|
|
||||||
;; bool: as in the uint8 case, where 1 is used for true and 0 for false
|
|
||||||
(defmethod enc :bool
|
|
||||||
[{:keys [value]}]
|
|
||||||
(left-pad (if value "1" "0")))
|
|
||||||
|
|
||||||
;; int<M>: enc(X) is the big-endian two’s complement encoding of X, padded on the
|
|
||||||
;; higher-order (left) side with 0xff for negative X and with zero bytes for
|
|
||||||
;; positive X such that the length is 32 bytes.
|
|
||||||
(defmethod enc :int
|
|
||||||
[{:keys [value]}]
|
|
||||||
(to-two-complement value))
|
|
||||||
|
|
||||||
;; uint<M>: enc(X) is the big-endian encoding of X, padded on the
|
|
||||||
;; higher-order (left) side with zero-bytes such that the length is 32 bytes.
|
|
||||||
(defmethod enc :uint
|
|
||||||
[{:keys [value]}]
|
|
||||||
(left-pad (number-to-hex value)))
|
|
||||||
|
|
||||||
;; address: as in the uint160 case
|
|
||||||
(defmethod enc :address
|
|
||||||
[{:keys [value]}]
|
|
||||||
(when (string? value)
|
|
||||||
(left-pad (string/replace value "0x" ""))))
|
|
||||||
|
|
||||||
;; bytes, of length k (which is assumed to be of type uint256):
|
|
||||||
;; enc(X) = enc(k) pad_right(X), i.e. the number of bytes is encoded as a
|
|
||||||
;; uint256 followed by the actual value of X as a byte sequence,
|
|
||||||
;; followed by the minimum number of zero-bytes such that len(enc(X))
|
|
||||||
;; is a multiple of 32.
|
|
||||||
;; bytes<M>: enc(X) is the sequence of bytes in X padded with trailing
|
|
||||||
;; zero-bytes to a length of 32 bytes.
|
|
||||||
(defmethod enc :bytes
|
|
||||||
[{:keys [value dynamic?]}]
|
|
||||||
;; in the examples of the abi specifications strings are passed for
|
|
||||||
;; bytes parameters, in our ens resolver we pass encoded bytes directly
|
|
||||||
;; for namehash, this handles both cases by checking if the value is already
|
|
||||||
;; hex
|
|
||||||
(let [encoded-value? (is-hex? value)
|
|
||||||
encoded-value (if encoded-value?
|
|
||||||
(subs value 2)
|
|
||||||
(utf8-to-hex value))]
|
|
||||||
(str (when dynamic? (enc {:type :int :value (/ (count encoded-value) 2)}))
|
|
||||||
(right-pad encoded-value))))
|
|
||||||
|
|
||||||
;; string: enc(X) = enc(enc_utf8(X)), i.e. X is utf-8 encoded and this
|
|
||||||
;; value is interpreted as of bytes type and encoded further.
|
|
||||||
;; Note that the length used in this subsequent encoding is the number
|
|
||||||
;; of bytes of the utf-8 encoded string, not its number of characters.
|
|
||||||
(defmethod enc :string
|
|
||||||
[{:keys [value dynamic?]}]
|
|
||||||
(enc {:type :bytes :value value :dynamic? dynamic?}))
|
|
||||||
|
|
||||||
;; fixed<M>x<N>: enc(X) is enc(X * 10**N) where X * 10**N is
|
|
||||||
;; interpreted as a int256.
|
|
||||||
(defmethod enc :fixed
|
|
||||||
[{:keys [value power]
|
|
||||||
:or {power 18}}]
|
|
||||||
(enc {:type :int
|
|
||||||
:value (* value (Math/pow 10 power))}))
|
|
||||||
|
|
||||||
;; ufixed: as in the ufixed128x18 case
|
|
||||||
(defmethod enc :ufixed
|
|
||||||
[{:keys [value power]
|
|
||||||
:or {power 18}}]
|
|
||||||
(enc {:type :uint
|
|
||||||
:value (* value (Math/pow 10 power))}))
|
|
||||||
|
|
||||||
;; T[k] for any T and k:
|
|
||||||
;; enc(X) = enc((X[0], ..., X[k-1]))
|
|
||||||
;; i.e. it is encoded as if it were a tuple with k elements of the same type.
|
|
||||||
|
|
||||||
;; T[] where X has k elements (k is assumed to be of type uint256):
|
|
||||||
;; enc(X) = enc(k) enc([X[0], ..., X[k-1]])
|
|
||||||
;; i.e. it is encoded as if it were an array of static size k,
|
|
||||||
;; prefixed with the number of elements.
|
|
||||||
(defmethod enc :array
|
|
||||||
[{:keys [value dynamic? array-of]}]
|
|
||||||
(str (when dynamic?
|
|
||||||
(enc {:type :int
|
|
||||||
:value (count value)}))
|
|
||||||
(enc {:type :tuple
|
|
||||||
:value (map #(assoc array-of :value %)
|
|
||||||
value)})))
|
|
||||||
|
|
||||||
;; (T1,...,Tk) for k >= 0 and any types T1, …, Tk
|
|
||||||
;; enc(X) = head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(k))
|
|
||||||
;; where X = (X(1), ..., X(k))
|
|
||||||
|
|
||||||
;; for Ti being static type:
|
|
||||||
;; head(X(i)) = enc(X(i))
|
|
||||||
;; tail(X(i)) = "" (the empty string)
|
|
||||||
|
|
||||||
;; for dynamic types:
|
|
||||||
;; head(X(i)) = enc(len(head(X(1)) ... head(X(k))
|
|
||||||
;; tail(X(1)) ... tail(X(i-1)) ))
|
|
||||||
;; tail(X(i)) = enc(X(i))
|
|
||||||
|
|
||||||
;; Note that in the dynamic case, head(X(i)) is well-defined since
|
|
||||||
;; the lengths of the head parts only depend on the types and not
|
|
||||||
;; the values. Its value is the offset of the beginning of tail(X(i))
|
|
||||||
;; relative to the start of enc(X).
|
|
||||||
(defmethod enc :tuple
|
|
||||||
[{:keys [value]}]
|
|
||||||
(let [[len x] (reduce
|
|
||||||
(fn [[len acc] {:keys [dynamic?] :as x}]
|
|
||||||
(let [enc-x (enc x)]
|
|
||||||
(if dynamic?
|
|
||||||
[(+ len 32)
|
|
||||||
(conj acc (assoc x :tail enc-x))]
|
|
||||||
[(+ len (/ (count enc-x) 2))
|
|
||||||
(conj acc (assoc x :head enc-x))])))
|
|
||||||
[0 []]
|
|
||||||
value)
|
|
||||||
[_ heads tails] (reduce (fn [[len heads tails] {:keys [head tail]}]
|
|
||||||
(if tail
|
|
||||||
[(+ len (/ (count tail) 2))
|
|
||||||
(conj heads (enc {:type :int :value len}))
|
|
||||||
(conj tails tail)]
|
|
||||||
[len
|
|
||||||
(conj heads head)
|
|
||||||
tails]))
|
|
||||||
[len [] []]
|
|
||||||
x)]
|
|
||||||
(apply str (concat heads tails))))
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; Parser for method signatures
|
|
||||||
;;
|
|
||||||
|
|
||||||
(spec/def ::params (spec/* (spec/cat ::param ::param
|
|
||||||
::separator (spec/? ::comma))))
|
|
||||||
|
|
||||||
(spec/def ::param (spec/cat ::type ::string
|
|
||||||
::size (spec/? ::number)
|
|
||||||
::x (spec/? ::x)
|
|
||||||
::power (spec/? ::number)
|
|
||||||
::array (spec/* ::array)))
|
|
||||||
|
|
||||||
(spec/def ::array (spec/cat ::open-bracket ::open-bracket
|
|
||||||
::size (spec/? ::number)
|
|
||||||
::close-bracket ::close-bracket))
|
|
||||||
|
|
||||||
(spec/def ::x #{\x})
|
|
||||||
|
|
||||||
(spec/def ::open-bracket #{\[})
|
|
||||||
|
|
||||||
(spec/def ::close-bracket #{\]})
|
|
||||||
|
|
||||||
(spec/def ::comma #{\,})
|
|
||||||
|
|
||||||
(spec/def ::number int?)
|
|
||||||
|
|
||||||
(spec/def ::string string?)
|
|
||||||
|
|
||||||
(defn- single-char [code]
|
|
||||||
(when-let [m (#{\, \[ \] \x} (first code))]
|
|
||||||
[1 m]))
|
|
||||||
|
|
||||||
(defn- number [code]
|
|
||||||
(when-let [m (re-find #"^[0-9]+" code)]
|
|
||||||
[(count m) (js/parseInt m)]))
|
|
||||||
|
|
||||||
(defn- string [s]
|
|
||||||
(when-let [m (re-find #"^[a-z]+" s)]
|
|
||||||
[(count m) m]))
|
|
||||||
|
|
||||||
(defn tokenise [code]
|
|
||||||
(when (seq code)
|
|
||||||
(if-let [[len token] (or (string code)
|
|
||||||
(single-char code)
|
|
||||||
(number code))]
|
|
||||||
(cons token (tokenise (subs code len)))
|
|
||||||
(throw (ex-info "Unexpected token" {:code code})))))
|
|
||||||
|
|
||||||
;; Definition: The following types are called “dynamic”:
|
|
||||||
;; - bytes
|
|
||||||
;; - string
|
|
||||||
;; - T[] for any T
|
|
||||||
;; - T[k] for any dynamic T and any k >= 0
|
|
||||||
;; - (T1,...,Tk) if Ti is dynamic for some 1 <= i <= k
|
|
||||||
(defn parse-param
|
|
||||||
"Takes a parsed parameter and returns a parameter that can
|
|
||||||
be encoded by associng the :dynamic? key for dynamic parameters
|
|
||||||
and recursively defining arrays"
|
|
||||||
[{::keys [type size array power] :as param}]
|
|
||||||
(if array
|
|
||||||
(let [{::keys [size]} (last array)]
|
|
||||||
{:type :array
|
|
||||||
:dynamic? (nil? size)
|
|
||||||
:array-of (parse-param (update param ::array butlast))})
|
|
||||||
(let [type (keyword type)
|
|
||||||
param {:type type
|
|
||||||
:dynamic? (or (= type :string)
|
|
||||||
(and (= type :bytes)
|
|
||||||
(nil? size)))
|
|
||||||
:size size}]
|
|
||||||
(if power
|
|
||||||
(assoc param :power power)
|
|
||||||
param))))
|
|
||||||
|
|
||||||
(defn parse-params [method-signature]
|
|
||||||
(let [tokens (tokenise (second (re-find #"\((.*)\)" method-signature)))
|
|
||||||
params (spec/conform ::params tokens)]
|
|
||||||
(if (spec/invalid? params)
|
|
||||||
(spec/explain-data ::params tokens)
|
|
||||||
(map #(parse-param (::param %))
|
|
||||||
params))))
|
|
||||||
|
|
||||||
(defn signature->method-id [signature]
|
|
||||||
(apply str (take 10 (ethereum/sha3 signature))))
|
|
||||||
|
|
||||||
(defn encode [method params]
|
|
||||||
(let [method-id (signature->method-id method)
|
|
||||||
params (map #(assoc %1 :value %2)
|
|
||||||
(parse-params method)
|
|
||||||
params)]
|
|
||||||
(str method-id (enc {:type :tuple
|
|
||||||
:value params}))))
|
|
||||||
|
|
||||||
;; ======= decode
|
|
||||||
|
|
||||||
(defn substr [val s l]
|
|
||||||
(subs val s (+ s l)))
|
|
||||||
|
|
||||||
;; "[]" -> 0 , "[1]" -> 1
|
|
||||||
(defn arr-size [val]
|
|
||||||
(int (apply str (rest (butlast val)))))
|
|
||||||
|
|
||||||
;; [2] -> 2 , [1] -> 1 , [] - > 1
|
|
||||||
(defn nested-size [val]
|
|
||||||
(let [num (arr-size val)]
|
|
||||||
(if (zero? num) 1 num)))
|
|
||||||
|
|
||||||
;; '("[1]" "[]") or nil
|
|
||||||
(defn list-of-nested-types [type]
|
|
||||||
(when-let [res (re-seq #"(\[[0-9]*\])" type)]
|
|
||||||
(map first res)))
|
|
||||||
|
|
||||||
(defn nested-name [type]
|
|
||||||
(let [ntypes (list-of-nested-types type)]
|
|
||||||
(if ntypes
|
|
||||||
(subs type 0 (- (count type) (count (last ntypes))))
|
|
||||||
type)))
|
|
||||||
|
|
||||||
(defn is-arr? [type]
|
|
||||||
(boolean (list-of-nested-types type)))
|
|
||||||
|
|
||||||
(defn is-dynamic-arr? [type]
|
|
||||||
(let [ntypes (list-of-nested-types type)]
|
|
||||||
(and ntypes (zero? (arr-size (last ntypes))))))
|
|
||||||
|
|
||||||
(defn static-arr-len [type]
|
|
||||||
(let [ntypes (list-of-nested-types type)]
|
|
||||||
(if ntypes
|
|
||||||
(nested-size (last ntypes))
|
|
||||||
1)))
|
|
||||||
|
|
||||||
(defn static-part-length [type]
|
|
||||||
(apply * (conj (map nested-size (or (list-of-nested-types type) '("1"))) 32)))
|
|
||||||
|
|
||||||
(defn offset-reducer [{:keys [cnt coll]} val]
|
|
||||||
(let [cnt' (+ cnt val)]
|
|
||||||
{:cnt cnt'
|
|
||||||
:coll (conj coll cnt')}))
|
|
||||||
|
|
||||||
(defn get-offsets [types]
|
|
||||||
(let [lengths (map static-part-length types)]
|
|
||||||
(conj (butlast (:coll (reduce offset-reducer {:cnt 0 :coll []} lengths))) 0)))
|
|
||||||
|
|
||||||
(defn hex-to-bytes [hex]
|
|
||||||
(let [number (hex-to-number (subs hex 0 64))
|
|
||||||
len (* (if (nil? number) 0 number) 2)]
|
|
||||||
(substr hex 64 len)))
|
|
||||||
|
|
||||||
(defn dyn-hex-to-value [hex type]
|
|
||||||
(cond
|
|
||||||
(string/starts-with? type "bytes")
|
|
||||||
(str "0x" (hex-to-bytes hex))
|
|
||||||
|
|
||||||
(string/starts-with? type "string")
|
|
||||||
(hex-to-utf8 (hex-to-bytes hex))))
|
|
||||||
|
|
||||||
(defn hex-to-bytesM [hex type]
|
|
||||||
(let [size (int (second (re-matches #"^bytes([0-9]*)" type)))]
|
|
||||||
(subs hex 0 (* 2 size))))
|
|
||||||
|
|
||||||
(defn hex-to-value [hex type]
|
|
||||||
(cond
|
|
||||||
(= "bool" type) (= hex "0000000000000000000000000000000000000000000000000000000000000001")
|
|
||||||
(string/starts-with? type "uint") (hex-to-number hex)
|
|
||||||
(string/starts-with? type "int") (hex-to-number hex)
|
|
||||||
(string/starts-with? type "address") (str "0x" (subs hex (- (count hex) 40)))
|
|
||||||
(string/starts-with? type "bytes") (hex-to-bytesM hex type)))
|
|
||||||
|
|
||||||
(defn dec-type [bytes]
|
|
||||||
(fn [offset type]
|
|
||||||
(cond
|
|
||||||
(is-arr? type)
|
|
||||||
|
|
||||||
(let [dyn-arr? (is-dynamic-arr? type)
|
|
||||||
arr-off (js/parseInt (str "0x" (substr bytes (* offset 2) 64)))
|
|
||||||
len (if dyn-arr?
|
|
||||||
(js/parseInt (str "0x" (substr bytes (* arr-off 2) 64)))
|
|
||||||
(static-arr-len type))
|
|
||||||
arr-start (if dyn-arr? (+ arr-off 32) offset)
|
|
||||||
|
|
||||||
nname (nested-name type)
|
|
||||||
nstatpartlen (static-part-length nname)
|
|
||||||
rnstatpartlen (* (js/Math.floor (/ (+ nstatpartlen 31) 32)) 32)]
|
|
||||||
(loop [res [] i 0]
|
|
||||||
(if (>= i (* len rnstatpartlen))
|
|
||||||
res
|
|
||||||
(recur (conj res ((dec-type bytes) (+ arr-start i) nname)) (+ i rnstatpartlen)))))
|
|
||||||
|
|
||||||
(or (re-matches #"^bytes(\[([0-9]*)\])*$" type)
|
|
||||||
(string/starts-with? type "string"))
|
|
||||||
|
|
||||||
(let [dyn-off (js/parseInt (str "0x" (substr bytes (* offset 2) 64)))
|
|
||||||
len (js/parseInt (str "0x" (substr bytes (* dyn-off 2) 64)))
|
|
||||||
rlen (js/Math.floor (/ (+ len 31) 32))
|
|
||||||
val (substr bytes (* dyn-off 2) (* (+ rlen 1) 64))]
|
|
||||||
(dyn-hex-to-value val type))
|
|
||||||
|
|
||||||
:else
|
|
||||||
|
|
||||||
(let [len (static-part-length type)
|
|
||||||
val (substr bytes (* offset 2) (* len 2))]
|
|
||||||
(hex-to-value val type)))))
|
|
||||||
|
|
||||||
(defn decode [bytes types]
|
|
||||||
(when bytes
|
|
||||||
(let [bytes (subs bytes 2)]
|
|
||||||
(when-not (empty? bytes)
|
|
||||||
(let [offsets (get-offsets types)]
|
|
||||||
(map #(when-not (= "0x" %) %)
|
|
||||||
(map (dec-type bytes) offsets types)))))))
|
|
@ -1,69 +0,0 @@
|
|||||||
(ns status-im.ethereum.abi-spec-test
|
|
||||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
|
||||||
[status-im.ethereum.abi-spec :as abi-spec]))
|
|
||||||
|
|
||||||
(deftest hex-to-number
|
|
||||||
(testing "hex number is less than 53 bits, it returns a number")
|
|
||||||
(is (= (abi-spec/hex-to-number "9")
|
|
||||||
9))
|
|
||||||
(is (= (abi-spec/hex-to-number "99999999")
|
|
||||||
2576980377))
|
|
||||||
(testing "hex number is less than 53 bits, it returns a string")
|
|
||||||
(is (= (abi-spec/hex-to-number "9999999999999999")
|
|
||||||
"11068046444225730969")))
|
|
||||||
|
|
||||||
(deftest enc
|
|
||||||
(is (= "000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" (abi-spec/enc {:type :address :value "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"}))))
|
|
||||||
|
|
||||||
(deftest test-encode
|
|
||||||
(is (= (abi-spec/encode "baz(uint32,bool)" [69 true])
|
|
||||||
"0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001"))
|
|
||||||
|
|
||||||
(is (= (abi-spec/encode "bar(bytes3[2])" [["abc" "def"]])
|
|
||||||
"0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000"))
|
|
||||||
|
|
||||||
(is (= (abi-spec/encode "sam(bytes,bool,uint256[])" ["dave" true [1 2 3]])
|
|
||||||
"0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"))
|
|
||||||
|
|
||||||
(is (= (abi-spec/encode "f(uint256,uint32[],bytes10,bytes)" [0x123 [0x456 0x789] "1234567890" "Hello, world!"])
|
|
||||||
"0x8be6524600000000000000000000000000000000000000000000000000000000000001230000000000000000000000000000000000000000000000000000000000000080313233343536373839300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004560000000000000000000000000000000000000000000000000000000000000789000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000"))
|
|
||||||
|
|
||||||
(is (= (abi-spec/encode "g(uint[][],string[])" [[[1 2] [3]] ["one" "two" "three"]])
|
|
||||||
"0xad6a3446000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000036f6e650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000374776f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000057468726565000000000000000000000000000000000000000000000000000000"))
|
|
||||||
|
|
||||||
(is (= (abi-spec/encode "getExpectedRate(address,address,uint256)" ["0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" 1000])
|
|
||||||
"0x809a9e55000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000000000000000003e8")))
|
|
||||||
|
|
||||||
(deftest test-decode
|
|
||||||
(is (= (abi-spec/decode "0x000000000000000000000000000000000000000000000000000000005bc741cd00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000013b86dbf1a83c9e6a492914a0ee39e8a5b7eb60700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e516d533152484e4a57414b356e426f6f57454d34654d644268707a35666e325764557473457357754a4b79356147000000000000000000000000000000000000"
|
|
||||||
["uint256" "bytes" "address" "uint256" "uint256"])
|
|
||||||
'(1539785165
|
|
||||||
"0x516d533152484e4a57414b356e426f6f57454d34654d644268707a35666e325764557473457357754a4b79356147"
|
|
||||||
"0x13b86dbf1a83c9e6a492914a0ee39e8a5b7eb607"
|
|
||||||
0
|
|
||||||
0)))
|
|
||||||
|
|
||||||
(is (= (abi-spec/decode "0x0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000d7621dc58210001"
|
|
||||||
["uint256" "uint256"])
|
|
||||||
'("1000000000000000000" "970000000000000001")))
|
|
||||||
|
|
||||||
(is (= (abi-spec/decode "0x000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000000000000000003e8"
|
|
||||||
["address" "address" "uint256"])
|
|
||||||
'("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" 1000)))
|
|
||||||
|
|
||||||
(is (= (abi-spec/decode "0x00000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001"
|
|
||||||
["uint32" "bool"])
|
|
||||||
'(69 true)))
|
|
||||||
|
|
||||||
(is (= (map abi-spec/hex-to-utf8
|
|
||||||
(first (abi-spec/decode "0x61626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000"
|
|
||||||
["bytes3[2]"])))
|
|
||||||
'("abc" "def")))
|
|
||||||
|
|
||||||
(is (= (abi-spec/decode "0x0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003"
|
|
||||||
["string" "bool" "uint256[]"])
|
|
||||||
'("dave" true [1 2 3])))
|
|
||||||
|
|
||||||
(is (= (abi-spec/decode "0x00000000000000000000000000000000000000000000000000000000000001230000000000000000000000000000000000000000000000000000000000000080313233343536373839300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004560000000000000000000000000000000000000000000000000000000000000789000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000"
|
|
||||||
["uint" "uint32[]" "bytes10" "bytes"])
|
|
||||||
'(291 [1110 1929] "31323334353637383930" "0x48656c6c6f2c20776f726c6421"))))
|
|
@ -1,10 +1,8 @@
|
|||||||
(ns status-im.ethereum.decode
|
(ns status-im.ethereum.decode
|
||||||
(:require [status-im.ethereum.abi-spec :as abi-spec]))
|
(:require [status-im.utils.money :as money]))
|
||||||
|
|
||||||
(defn uint
|
(defn uint
|
||||||
[hex]
|
[hex]
|
||||||
(first (abi-spec/decode hex ["uint"])))
|
(let [n (money/bignumber hex)]
|
||||||
|
(when n
|
||||||
(defn string
|
(.toString n 10))))
|
||||||
[hex]
|
|
||||||
(first (abi-spec/decode hex ["string"])))
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
(ns status-im.ethereum.ens
|
(ns status-im.ethereum.ens
|
||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[status-im.ethereum.json-rpc :as json-rpc]
|
[status-im.ethereum.json-rpc :as json-rpc]
|
||||||
[status-im.ethereum.abi-spec :as abi-spec]))
|
[status-im.native-module.core :as status]))
|
||||||
|
|
||||||
;; this is the addresses of ens registries for the different networks
|
;; this is the addresses of ens registries for the different networks
|
||||||
(def ens-registries
|
(def ens-registries
|
||||||
@ -65,7 +65,7 @@
|
|||||||
:params [chain-id ens-name]
|
:params [chain-id ens-name]
|
||||||
:on-success
|
:on-success
|
||||||
;;NOTE: returns a timestamp in s and we want ms
|
;;NOTE: returns a timestamp in s and we want ms
|
||||||
#(cb (* (js/Number (abi-spec/hex-to-number %)) 1000))}))
|
#(cb (* (js/Number (status/hex-to-number %)) 1000))}))
|
||||||
|
|
||||||
(defn register-prepare-tx
|
(defn register-prepare-tx
|
||||||
[chain-id from ens-name pubkey cb]
|
[chain-id from ens-name pubkey cb]
|
||||||
|
@ -391,6 +391,33 @@
|
|||||||
(log/debug "[native-module] identicon")
|
(log/debug "[native-module] identicon")
|
||||||
(.identicon ^js (status) seed))
|
(.identicon ^js (status) seed))
|
||||||
|
|
||||||
|
(defn encode-transfer
|
||||||
|
[to-norm amount-hex]
|
||||||
|
(log/debug "[native-module] encode-transfer")
|
||||||
|
(.encodeTransfer ^js (status) to-norm amount-hex))
|
||||||
|
|
||||||
|
(defn encode-function-call
|
||||||
|
[method params]
|
||||||
|
(log/debug "[native-module] encode-function-call")
|
||||||
|
(.encodeFunctionCall ^js (status) method (types/clj->json params)))
|
||||||
|
|
||||||
|
(defn decode-parameters
|
||||||
|
[bytes-string types]
|
||||||
|
(log/debug "[native-module] decode-parameters")
|
||||||
|
(let [json-str (.decodeParameters ^js (status) (types/clj->json {:bytesString bytes-string :types types}))]
|
||||||
|
(types/json->clj json-str)))
|
||||||
|
|
||||||
|
(defn hex-to-number
|
||||||
|
[hex]
|
||||||
|
(log/debug "[native-module] hex-to-number")
|
||||||
|
(let [json-str (.hexToNumber ^js (status) hex)]
|
||||||
|
(types/json->clj json-str)))
|
||||||
|
|
||||||
|
(defn number-to-hex
|
||||||
|
[num]
|
||||||
|
(log/debug "[native-module] number-to-hex")
|
||||||
|
(.numberToHex ^js (status) (str num)))
|
||||||
|
|
||||||
(defn identicon-async
|
(defn identicon-async
|
||||||
"Generate a icon based on a string, asynchronously"
|
"Generate a icon based on a string, asynchronously"
|
||||||
[seed callback]
|
[seed callback]
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[status-im.ethereum.abi-spec :as abi-spec]
|
|
||||||
[status-im.ethereum.core :as ethereum]
|
[status-im.ethereum.core :as ethereum]
|
||||||
[status-im.ethereum.eip55 :as eip55]
|
[status-im.ethereum.eip55 :as eip55]
|
||||||
[status-im.ethereum.json-rpc :as json-rpc]
|
[status-im.ethereum.json-rpc :as json-rpc]
|
||||||
@ -105,16 +104,16 @@
|
|||||||
(sign-message cofx)
|
(sign-message cofx)
|
||||||
(let [tx-obj-to-send (merge tx-obj
|
(let [tx-obj-to-send (merge tx-obj
|
||||||
(when gas
|
(when gas
|
||||||
{:gas (str "0x" (abi-spec/number-to-hex gas))})
|
{:gas (str "0x" (status/number-to-hex gas))})
|
||||||
(when gasPrice
|
(when gasPrice
|
||||||
{:gasPrice (str "0x" (abi-spec/number-to-hex gasPrice))})
|
{:gasPrice (str "0x" (status/number-to-hex gasPrice))})
|
||||||
(when nonce
|
(when nonce
|
||||||
{:nonce (str "0x" (abi-spec/number-to-hex nonce))})
|
{:nonce (str "0x" (status/number-to-hex nonce))})
|
||||||
(when maxPriorityFeePerGas
|
(when maxPriorityFeePerGas
|
||||||
{:maxPriorityFeePerGas (str "0x" (abi-spec/number-to-hex
|
{:maxPriorityFeePerGas (str "0x" (status/number-to-hex
|
||||||
(js/parseInt maxPriorityFeePerGas)))})
|
(js/parseInt maxPriorityFeePerGas)))})
|
||||||
(when maxFeePerGas
|
(when maxFeePerGas
|
||||||
{:maxFeePerGas (str "0x" (abi-spec/number-to-hex
|
{:maxFeePerGas (str "0x" (status/number-to-hex
|
||||||
(js/parseInt maxFeePerGas)))}))]
|
(js/parseInt maxFeePerGas)))}))]
|
||||||
(when-not in-progress?
|
(when-not in-progress?
|
||||||
{:db (update db :signing/sign assoc :error nil :in-progress? true)
|
{:db (update db :signing/sign assoc :error nil :in-progress? true)
|
||||||
@ -174,7 +173,7 @@
|
|||||||
(let [{:keys [symbol decimals] :as token} (tokens/address->token (:wallet/all-tokens db) to)]
|
(let [{:keys [symbol decimals] :as token} (tokens/address->token (:wallet/all-tokens db) to)]
|
||||||
(when (and token data (string? data))
|
(when (and token data (string? data))
|
||||||
(when-let [type (get-method-type data)]
|
(when-let [type (get-method-type data)]
|
||||||
(let [[address value _] (abi-spec/decode
|
(let [[address value _] (status/decode-parameters
|
||||||
(str "0x" (subs data 10))
|
(str "0x" (subs data 10))
|
||||||
(if (= type :approve-and-call) ["address" "uint256" "bytes"] ["address" "uint256"]))]
|
(if (= type :approve-and-call) ["address" "uint256" "bytes"] ["address" "uint256"]))]
|
||||||
(when (and address value)
|
(when (and address value)
|
||||||
@ -449,7 +448,7 @@
|
|||||||
{:events [:wallet.ui/sign-transaction-button-clicked-from-chat]}
|
{:events [:wallet.ui/sign-transaction-button-clicked-from-chat]}
|
||||||
[{:keys [db] :as cofx} {:keys [to amount from token]}]
|
[{:keys [db] :as cofx} {:keys [to amount from token]}]
|
||||||
(let [{:keys [symbol address]} token
|
(let [{:keys [symbol address]} token
|
||||||
amount-hex (str "0x" (abi-spec/number-to-hex amount))
|
amount-hex (str "0x" (status/number-to-hex amount))
|
||||||
to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))
|
to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))
|
||||||
from-address (:address from)
|
from-address (:address from)
|
||||||
identity (:current-chat-id db)
|
identity (:current-chat-id db)
|
||||||
@ -468,9 +467,7 @@
|
|||||||
:from from-address
|
:from from-address
|
||||||
:chat-id identity
|
:chat-id identity
|
||||||
:command? true
|
:command? true
|
||||||
:data (abi-spec/encode
|
:data (status/encode-transfer to-norm amount-hex)})}))
|
||||||
"transfer(address,uint256)"
|
|
||||||
[to-norm amount-hex])})}))
|
|
||||||
{:db db
|
{:db db
|
||||||
::json-rpc/call
|
::json-rpc/call
|
||||||
[{:method "wakuext_requestAddressForTransaction"
|
[{:method "wakuext_requestAddressForTransaction"
|
||||||
@ -487,7 +484,7 @@
|
|||||||
[{:keys [db] :as cofx} {:keys [amount from token]}]
|
[{:keys [db] :as cofx} {:keys [amount from token]}]
|
||||||
(let [{:keys [request-parameters chat-id]} (:wallet/prepare-transaction db)
|
(let [{:keys [request-parameters chat-id]} (:wallet/prepare-transaction db)
|
||||||
{:keys [symbol address]} token
|
{:keys [symbol address]} token
|
||||||
amount-hex (str "0x" (abi-spec/number-to-hex amount))
|
amount-hex (str "0x" (status/number-to-hex amount))
|
||||||
to-norm (:address request-parameters)
|
to-norm (:address request-parameters)
|
||||||
from-address (:address from)]
|
from-address (:address from)]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
@ -507,15 +504,13 @@
|
|||||||
:command? true
|
:command? true
|
||||||
:message-id (:id request-parameters)
|
:message-id (:id request-parameters)
|
||||||
:chat-id chat-id
|
:chat-id chat-id
|
||||||
:data (abi-spec/encode
|
:data (status/encode-transfer to-norm amount-hex)})})))))
|
||||||
"transfer(address,uint256)"
|
|
||||||
[to-norm amount-hex])})})))))
|
|
||||||
|
|
||||||
(fx/defn sign-transaction-button-clicked
|
(fx/defn sign-transaction-button-clicked
|
||||||
{:events [:wallet.ui/sign-transaction-button-clicked]}
|
{:events [:wallet.ui/sign-transaction-button-clicked]}
|
||||||
[{:keys [db] :as cofx} {:keys [to amount from token gas gasPrice maxFeePerGas maxPriorityFeePerGas]}]
|
[{:keys [db] :as cofx} {:keys [to amount from token gas gasPrice maxFeePerGas maxPriorityFeePerGas]}]
|
||||||
(let [{:keys [symbol address]} token
|
(let [{:keys [symbol address]} token
|
||||||
amount-hex (str "0x" (abi-spec/number-to-hex amount))
|
amount-hex (str "0x" (status/number-to-hex amount))
|
||||||
to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))
|
to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))
|
||||||
from-address (:address from)]
|
from-address (:address from)]
|
||||||
(fx/merge cofx
|
(fx/merge cofx
|
||||||
@ -535,9 +530,7 @@
|
|||||||
{:to to-norm
|
{:to to-norm
|
||||||
:value amount-hex}
|
:value amount-hex}
|
||||||
{:to (ethereum/normalized-hex address)
|
{:to (ethereum/normalized-hex address)
|
||||||
:data (abi-spec/encode
|
:data (status/encode-transfer to-norm amount-hex)}))}))))
|
||||||
"transfer(address,uint256)"
|
|
||||||
[to-norm amount-hex])}))}))))
|
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:signing/get-transaction-by-hash-fx
|
:signing/get-transaction-by-hash-fx
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
(ns status-im.signing.core-test
|
(ns status-im.signing.core-test
|
||||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||||
[status-im.signing.core :as signing]
|
[status-im.signing.core :as signing]
|
||||||
[status-im.ethereum.abi-spec :as abi-spec]))
|
[status-im.native-module.core :as status]))
|
||||||
|
|
||||||
(deftest signing-test
|
(deftest signing-test
|
||||||
(testing "showing sheet"
|
(testing "showing sheet"
|
||||||
(let [to "0x2f88d65f3cb52605a54a833ae118fb1363acccd2"
|
(let [to "0x2f88d65f3cb52605a54a833ae118fb1363acccd2"
|
||||||
contract "0xc55cf4b03948d7ebc8b9e8bad92643703811d162"
|
contract "0xc55cf4b03948d7ebc8b9e8bad92643703811d162"
|
||||||
amount1-hex (str "0x" (abi-spec/number-to-hex "10000000000000000000"))
|
amount1-hex (str "0x" (status/number-to-hex "10000000000000000000"))
|
||||||
amount2-hex (str "0x" (abi-spec/number-to-hex "100000000000000000000"))
|
amount2-hex (str "0x" (status/number-to-hex "100000000000000000000"))
|
||||||
data (abi-spec/encode "transfer(address,uint256)" [to amount2-hex])
|
data (status/encode-transfer to amount2-hex)
|
||||||
first-tx {:tx-obj {:to to
|
first-tx {:tx-obj {:to to
|
||||||
:from nil
|
:from nil
|
||||||
:value amount1-hex}}
|
:value amount1-hex}}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
(ns status-im.signing.keycard
|
(ns status-im.signing.keycard
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[status-im.ethereum.abi-spec :as abi-spec]
|
|
||||||
[status-im.native-module.core :as status]
|
[status-im.native-module.core :as status]
|
||||||
[status-im.utils.fx :as fx]
|
[status-im.utils.fx :as fx]
|
||||||
[status-im.i18n.i18n :as i18n]
|
[status-im.i18n.i18n :as i18n]
|
||||||
@ -36,15 +35,15 @@
|
|||||||
:message-id message-id
|
:message-id message-id
|
||||||
:command? command?}
|
:command? command?}
|
||||||
maxPriorityFeePerGas
|
maxPriorityFeePerGas
|
||||||
(assoc :maxPriorityFeePerGas (str "0x" (abi-spec/number-to-hex
|
(assoc :maxPriorityFeePerGas (str "0x" (status/number-to-hex
|
||||||
(js/parseInt maxPriorityFeePerGas))))
|
(js/parseInt maxPriorityFeePerGas))))
|
||||||
maxFeePerGas
|
maxFeePerGas
|
||||||
(assoc :maxFeePerGas (str "0x" (abi-spec/number-to-hex
|
(assoc :maxFeePerGas (str "0x" (status/number-to-hex
|
||||||
(js/parseInt maxFeePerGas))))
|
(js/parseInt maxFeePerGas))))
|
||||||
gas
|
gas
|
||||||
(assoc :gas (str "0x" (abi-spec/number-to-hex gas)))
|
(assoc :gas (str "0x" (status/number-to-hex gas)))
|
||||||
gasPrice
|
gasPrice
|
||||||
(assoc :gasPrice (str "0x" (abi-spec/number-to-hex gasPrice)))
|
(assoc :gasPrice (str "0x" (status/number-to-hex gasPrice)))
|
||||||
data
|
data
|
||||||
(assoc :data data)
|
(assoc :data data)
|
||||||
nonce
|
nonce
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im.ethereum.json-rpc :as json-rpc]
|
[status-im.ethereum.json-rpc :as json-rpc]
|
||||||
[status-im.ethereum.decode :as decode]
|
[status-im.ethereum.decode :as decode]
|
||||||
[status-im.ethereum.abi-spec :as abi-spec]
|
[status-im.utils.datetime :as time]
|
||||||
[status-im.utils.datetime :as time]))
|
[status-im.native-module.core :as status]))
|
||||||
|
|
||||||
(defn get-block [block callback]
|
(defn get-block [block callback]
|
||||||
(json-rpc/call
|
(json-rpc/call
|
||||||
@ -31,7 +31,7 @@
|
|||||||
(fn [res]
|
(fn [res]
|
||||||
(reset! latest-block res)
|
(reset! latest-block res)
|
||||||
(get-block
|
(get-block
|
||||||
(str "0x" (abi-spec/number-to-hex
|
(str "0x" (status/number-to-hex
|
||||||
(last-loaded-block-number)))
|
(last-loaded-block-number)))
|
||||||
(fn [res]
|
(fn [res]
|
||||||
(reset! last-loaded-block res))))))]
|
(reset! last-loaded-block res))))))]
|
||||||
|
@ -79,11 +79,29 @@
|
|||||||
(.initKeystore
|
(.initKeystore
|
||||||
native-status
|
native-status
|
||||||
(str test-dir "/keystore/" key-uid))))
|
(str test-dir "/keystore/" key-uid))))
|
||||||
|
|
||||||
:identicon (fn [pk]
|
:identicon (fn [pk]
|
||||||
(.identicon native-status pk))
|
(.identicon native-status pk))
|
||||||
|
|
||||||
|
:encodeTransfer (fn [to-norm amount-hex]
|
||||||
|
(.encodeTransfer native-status to-norm amount-hex))
|
||||||
|
|
||||||
|
:encodeFunctionCall (fn [method params-json]
|
||||||
|
(.encodeFunctionCall native-status method params-json))
|
||||||
|
|
||||||
|
:decodeParameters (fn [decode-param-json]
|
||||||
|
(.decodeParameters native-status decode-param-json))
|
||||||
|
|
||||||
|
:hexToNumber (fn [hex]
|
||||||
|
(.hexToNumber native-status hex))
|
||||||
|
|
||||||
|
:numberToHex (fn [num-str]
|
||||||
|
(.numberToHex native-status num-str))
|
||||||
|
|
||||||
:validateMnemonic (fn [json callback]
|
:validateMnemonic (fn [json callback]
|
||||||
(callback
|
(callback
|
||||||
(.validateMnemonic
|
(.validateMnemonic
|
||||||
native-status
|
native-status
|
||||||
json)))
|
json)))
|
||||||
|
|
||||||
:startLocalNotifications identity}))
|
:startLocalNotifications identity}))
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
(ns ^{:doc "Implementation of varint based on https://github.com/chrisdickinson/varint"}
|
|
||||||
status-im.utils.varint
|
|
||||||
(:require [status-im.ethereum.abi-spec :as abi-spec]
|
|
||||||
["web3-utils" :as utils]))
|
|
||||||
|
|
||||||
(def most-significant-bit 0x80)
|
|
||||||
(def biggest-int-per-byte 0x7F)
|
|
||||||
(def biggest-int 2147483648) ;; 2^31
|
|
||||||
|
|
||||||
(defn encode [num]
|
|
||||||
(loop [num num
|
|
||||||
out []]
|
|
||||||
(if (>= num 128)
|
|
||||||
(recur (if (>= num biggest-int)
|
|
||||||
(/ num 128)
|
|
||||||
(bit-shift-right num 7))
|
|
||||||
(conj out (bit-or (bit-and num 0xFF)
|
|
||||||
most-significant-bit)))
|
|
||||||
(conj out (bit-or num 0)))))
|
|
||||||
|
|
||||||
(defn encode-hex [num]
|
|
||||||
(reduce (fn [hex current-bit]
|
|
||||||
(str hex
|
|
||||||
(.leftPad utils
|
|
||||||
(abi-spec/number-to-hex current-bit)
|
|
||||||
2)))
|
|
||||||
""
|
|
||||||
(encode num)))
|
|
||||||
|
|
||||||
(defn add-b-to-res
|
|
||||||
[res b shift]
|
|
||||||
(+ res (if (< shift 28)
|
|
||||||
(bit-shift-left (bit-and b biggest-int-per-byte)
|
|
||||||
shift)
|
|
||||||
(* (bit-and b biggest-int-per-byte)
|
|
||||||
shift shift))))
|
|
||||||
|
|
||||||
(defn decode [buf]
|
|
||||||
(loop [res 0
|
|
||||||
shift 0
|
|
||||||
[b & rest-buf] buf]
|
|
||||||
(if (>= b most-significant-bit)
|
|
||||||
(recur (add-b-to-res res b shift)
|
|
||||||
(+ shift 7)
|
|
||||||
rest-buf)
|
|
||||||
(add-b-to-res res b shift))))
|
|
||||||
|
|
||||||
(defn decode-hex [hex]
|
|
||||||
(->> hex
|
|
||||||
(partition 2)
|
|
||||||
(mapv #(abi-spec/hex-to-number (apply str %)))
|
|
||||||
decode))
|
|
@ -1,28 +0,0 @@
|
|||||||
(ns status-im.utils.varint-test
|
|
||||||
(:require [cljs.test :refer-macros [deftest is]]
|
|
||||||
[status-im.utils.varint :as varint]))
|
|
||||||
|
|
||||||
(deftest encode
|
|
||||||
(is (= (varint/encode-hex 0x0)
|
|
||||||
"00"))
|
|
||||||
(is (= (varint/encode-hex 0x70)
|
|
||||||
"70"))
|
|
||||||
(is (= (varint/encode-hex 0xe3)
|
|
||||||
"e301")))
|
|
||||||
|
|
||||||
(deftest decode
|
|
||||||
(is (= (varint/decode-hex "00")
|
|
||||||
0x0))
|
|
||||||
(is (= (varint/decode-hex "70")
|
|
||||||
0x70))
|
|
||||||
(is (= (varint/decode-hex "e301")
|
|
||||||
0xe3)))
|
|
||||||
|
|
||||||
(defn test-roundtrip [n]
|
|
||||||
(= (varint/decode-hex (varint/encode-hex n))
|
|
||||||
n))
|
|
||||||
|
|
||||||
(deftest roundtrip
|
|
||||||
(is (test-roundtrip 0))
|
|
||||||
(is (test-roundtrip 23948))
|
|
||||||
(is (test-roundtrip 2684453)))
|
|
@ -3,7 +3,7 @@
|
|||||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||||
"owner": "status-im",
|
"owner": "status-im",
|
||||||
"repo": "status-go",
|
"repo": "status-go",
|
||||||
"version": "v0.109.4",
|
"version": "v0.110.1",
|
||||||
"commit-sha1": "6f93913be5559852ad456827beb26a7f4ccc2509",
|
"commit-sha1": "a182f3e699f290776a1f1b3df8e2341c67b3f814",
|
||||||
"src-sha256": "08aa2x38739wg6hrcv8rxmc2rhmv2nr3jnh9y5wqrf2hldvprplx"
|
"src-sha256": "1hrqmm4db4vbgwjmvqzbilza6fwgb2hns1bsx4vzdpvjqfy3akrv"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user