From 0c0e9ae4a3c422c5603341369addfbfb450b38a4 Mon Sep 17 00:00:00 2001 From: Haofeng Jiang Date: Fri, 17 Nov 2023 16:40:45 +0800 Subject: [PATCH 1/4] completion some client interface --- Client.php | 25 +++++- MPCClient.php | 14 +++ MPCPrimeBrokerClient.php | 187 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 MPCPrimeBrokerClient.php diff --git a/Client.php b/Client.php index 4e426c8..925bce0 100644 --- a/Client.php +++ b/Client.php @@ -114,6 +114,18 @@ function getCoinDetails(string $coin) return $this->request("GET", "/v1/custody/coin_info/", $params); } + /*** + * Get Support Coins + * @return mixed + * @throws Exception + */ + function getSupportedCoins() + { + $params = [ + ]; + return $this->request("GET", "/v1/custody/get_supported_coins/", $params); + } + /*** * Get New Deposit Address * @param string $coin @@ -307,6 +319,17 @@ function getPendingTransactions(array $params = []) return $this->request("GET", "/v1/custody/pending_transactions/", $params); } + /*** + * Get transactions by requestIds + * @param string $requestIds + * @return mixed|string + * @throws Exception + */ + function getTransactionsByRequestid(string $requestIds) + { + return $this->request("GET", "/v1/custody/transactions_by_request_ids/", ["request_ids" => $requestIds]); + } + /*** * Get transactions by txid * @param string $txid @@ -477,6 +500,4 @@ function getStakingHistory(array $params = []) { return $this->request("GET", "/v1/custody/staking_history/", $params); } - - } \ No newline at end of file diff --git a/MPCClient.php b/MPCClient.php index 8656477..0d909df 100644 --- a/MPCClient.php +++ b/MPCClient.php @@ -666,4 +666,18 @@ function signMessageByCoboIds(string $coboIds) return $this->request("GET", "/v1/custody/mpc/sign_messages_by_cobo_ids/", $params); } + + /*** + * retry double check + * string $requestId + * @return mixed|string + */ + function retryDoubleCheck(string $requestId) + { + $params = [ + "request_id" => $requestId, + ]; + + return $this->request("POST", "/v1/custody/mpc/retry_double_check/", $params); + } } \ No newline at end of file diff --git a/MPCPrimeBrokerClient.php b/MPCPrimeBrokerClient.php new file mode 100644 index 0000000..70b8f30 --- /dev/null +++ b/MPCPrimeBrokerClient.php @@ -0,0 +1,187 @@ +apiKey = $apiSigner->getPublicKey(); + $this->apiSigner = $apiSigner; + $this->coboPub = $config['coboPub']; + $this->host = $config['host']; + $this->debug = $debug; + } + + /** + * @throws Exception + */ + function request(string $method, string $path, array $data) + { + $ch = curl_init(); + $sorted_data = $this->sortData($data); + list($microsecond, $second) = explode(' ', microtime()); + $nonce = (float)sprintf('%.0f', (floatval($microsecond) + floatval($second)) * 1000); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_HEADER, 1); + curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); + + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Biz-Api-Key:" . $this->apiKey, + "Biz-Api-Nonce:" . $nonce, + "Biz-Api-Signature:" . $this->apiSigner->sign(join("|", [$method, $path, $nonce, $sorted_data])) + ]); + + + if ($method == "POST") { + curl_setopt($ch, CURLOPT_URL, $this->host . $path); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data); + } else { + curl_setopt($ch, CURLOPT_URL, $this->host . $path . "?" . $sorted_data); + } + if ($this->debug) { + echo "request >>>>>>>>\n"; + echo join("|", [$method, $path, $nonce, $sorted_data]), "\n"; + } + + list($header, $body) = explode("\r\n\r\n", curl_exec($ch), 2); + preg_match("/biz_timestamp: (?[0-9]*)/i", $header, $match); + $timestamp = $match["timestamp"]; + preg_match("/biz_resp_signature: (?[0-9abcdef]*)/i", $header, $match); + $signature = $match["signature"]; + + if ($this->debug) { + echo "response <<<<<<<<\n"; + echo "$body|$timestamp", "\n"; + echo "$signature", "\n"; + } + if ($this->verifyEcdsa($body, $timestamp, $signature) != 1) { + throw new Exception("signature verify fail"); + } + curl_close($ch); + return json_decode($body); + } + + private function sortData(array $data): string + { + ksort($data); + $result = []; + foreach ($data as $key => $val) { + array_push($result, $key . "=" . urlencode($val)); + } + return join("&", $result); + } + + function verifyEcdsa(string $message, string $timestamp, string $signature): bool + { + $message = hash("sha256", hash("sha256", "$message|$timestamp", True), True); + $ec = new EC('secp256k1'); + $key = $ec->keyFromPublic($this->coboPub, "hex"); + return $key->verify(bin2hex($message), $signature); + } + + /*** + * create binding + * @param string $userId + * @return mixed|string + */ + function createBinding(string $userId) + { + $params = [ + "user_id" => $userId, + ]; + return $this->request("POST", "/v1/custody/auth/create_binding/", $params); + } + + /*** + * query binding + * @param string $binderId + * @return mixed|string + */ + function queryBinding(string $binderId) + { + $params = [ + "binder_id" => $binderId, + ]; + return $this->request("GET", "/v1/custody/auth/query_binding/", $params); + } + + /*** + * query user auth + * @param string $userId + * @return mixed|string + */ + function queryUserAuth(string $userId) + { + $params = [ + "user_id" => $userId, + ]; + return $this->request("GET", "/v1/custody/auth/query_user_auth/", $params); + } + + /*** + * bind addresses + * @param string $userId + * @param string $addresses + * @return mixed|string + */ + function bindAddresses(string $userId, string $addresses) + { + $params = [ + "user_id" => $userId, + "addresses" => $addresses, + ]; + return $this->request("POST", "/v1/custody/auth/bind_addresses/", $params); + } + + /*** + * change binding + * @param string $userId + * @return mixed|string + */ + function changeBinding(string $userId) + { + $params = [ + "user_id" => $userId, + ]; + return $this->request("POST", "/v1/custody/auth/change_binding/", $params); + } + + /*** + * unbind binding + * @param string $userId + * @return mixed|string + */ + function unbindBinding(string $userId) + { + $params = [ + "user_id" => $userId, + ]; + return $this->request("POST", "/v1/custody/auth/unbind_binding/", $params); + } + + /*** + * query statement + * @param string $statementId + * @return mixed|string + */ + function queryStatement(string $statementId) + { + $params = [ + "statement_id" => $statementId, + ]; + return $this->request("GET", "/v1/custody/auth/query_statement/", $params); + } +} From 6c3178da1322fd8a01ed6e7f9a9e4bad3a590777 Mon Sep 17 00:00:00 2001 From: Haofeng Jiang Date: Mon, 20 Nov 2023 14:21:07 +0800 Subject: [PATCH 2/4] update --- Client.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Client.php b/Client.php index 925bce0..f08396e 100644 --- a/Client.php +++ b/Client.php @@ -121,8 +121,7 @@ function getCoinDetails(string $coin) */ function getSupportedCoins() { - $params = [ - ]; + $params = []; return $this->request("GET", "/v1/custody/get_supported_coins/", $params); } From ecc82b71c7b176f0d062d19b2848d47e1939159e Mon Sep 17 00:00:00 2001 From: Haofeng Jiang Date: Mon, 20 Nov 2023 16:15:03 +0800 Subject: [PATCH 3/4] update --- MPCPrimeBrokerClient.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MPCPrimeBrokerClient.php b/MPCPrimeBrokerClient.php index 70b8f30..8548a77 100644 --- a/MPCPrimeBrokerClient.php +++ b/MPCPrimeBrokerClient.php @@ -102,7 +102,7 @@ function createBinding(string $userId) $params = [ "user_id" => $userId, ]; - return $this->request("POST", "/v1/custody/auth/create_binding/", $params); + return $this->request("POST", "/v1/custody/guards/create_binding/", $params); } /*** @@ -115,7 +115,7 @@ function queryBinding(string $binderId) $params = [ "binder_id" => $binderId, ]; - return $this->request("GET", "/v1/custody/auth/query_binding/", $params); + return $this->request("GET", "/v1/custody/guards/query_binding/", $params); } /*** @@ -128,7 +128,7 @@ function queryUserAuth(string $userId) $params = [ "user_id" => $userId, ]; - return $this->request("GET", "/v1/custody/auth/query_user_auth/", $params); + return $this->request("GET", "/v1/custody/guards/query_user_auth/", $params); } /*** @@ -143,7 +143,7 @@ function bindAddresses(string $userId, string $addresses) "user_id" => $userId, "addresses" => $addresses, ]; - return $this->request("POST", "/v1/custody/auth/bind_addresses/", $params); + return $this->request("POST", "/v1/custody/guards/bind_addresses/", $params); } /*** @@ -156,7 +156,7 @@ function changeBinding(string $userId) $params = [ "user_id" => $userId, ]; - return $this->request("POST", "/v1/custody/auth/change_binding/", $params); + return $this->request("POST", "/v1/custody/guards/change_binding/", $params); } /*** @@ -169,7 +169,7 @@ function unbindBinding(string $userId) $params = [ "user_id" => $userId, ]; - return $this->request("POST", "/v1/custody/auth/unbind_binding/", $params); + return $this->request("POST", "/v1/custody/guards/unbind_binding/", $params); } /*** @@ -182,6 +182,6 @@ function queryStatement(string $statementId) $params = [ "statement_id" => $statementId, ]; - return $this->request("GET", "/v1/custody/auth/query_statement/", $params); + return $this->request("GET", "/v1/custody/guards/query_statement/", $params); } } From 47026d9edbbcf5c9525807772bc4e694147bac2a Mon Sep 17 00:00:00 2001 From: Haofeng Jiang Date: Mon, 20 Nov 2023 17:55:36 +0800 Subject: [PATCH 4/4] update --- MPCPrimeBrokerClient.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/MPCPrimeBrokerClient.php b/MPCPrimeBrokerClient.php index 8548a77..0687949 100644 --- a/MPCPrimeBrokerClient.php +++ b/MPCPrimeBrokerClient.php @@ -102,7 +102,7 @@ function createBinding(string $userId) $params = [ "user_id" => $userId, ]; - return $this->request("POST", "/v1/custody/guards/create_binding/", $params); + return $this->request("POST", "/v1/custody/guard/create_binding/", $params); } /*** @@ -115,7 +115,7 @@ function queryBinding(string $binderId) $params = [ "binder_id" => $binderId, ]; - return $this->request("GET", "/v1/custody/guards/query_binding/", $params); + return $this->request("GET", "/v1/custody/guard/query_binding/", $params); } /*** @@ -128,7 +128,7 @@ function queryUserAuth(string $userId) $params = [ "user_id" => $userId, ]; - return $this->request("GET", "/v1/custody/guards/query_user_auth/", $params); + return $this->request("GET", "/v1/custody/guard/query_user_auth/", $params); } /*** @@ -143,7 +143,7 @@ function bindAddresses(string $userId, string $addresses) "user_id" => $userId, "addresses" => $addresses, ]; - return $this->request("POST", "/v1/custody/guards/bind_addresses/", $params); + return $this->request("POST", "/v1/custody/guard/bind_addresses/", $params); } /*** @@ -156,7 +156,7 @@ function changeBinding(string $userId) $params = [ "user_id" => $userId, ]; - return $this->request("POST", "/v1/custody/guards/change_binding/", $params); + return $this->request("POST", "/v1/custody/guard/change_binding/", $params); } /*** @@ -169,7 +169,7 @@ function unbindBinding(string $userId) $params = [ "user_id" => $userId, ]; - return $this->request("POST", "/v1/custody/guards/unbind_binding/", $params); + return $this->request("POST", "/v1/custody/guard/unbind_binding/", $params); } /*** @@ -182,6 +182,6 @@ function queryStatement(string $statementId) $params = [ "statement_id" => $statementId, ]; - return $this->request("GET", "/v1/custody/guards/query_statement/", $params); + return $this->request("GET", "/v1/custody/guard/query_statement/", $params); } }