From 8e6138b0b413ba6011e5c4ae127b66246a56956b Mon Sep 17 00:00:00 2001 From: DhananjayPurohit Date: Wed, 28 Aug 2024 19:11:14 +0530 Subject: [PATCH 1/7] feat: add tnc to token --- server/migrations/0001_key_data_table.sql | 3 +- token-server/src/endpoints/token.rs | 27 +++++++ token-server/src/main.rs | 1 + token-server/src/server_config.rs | 7 +- token-server/tnc.html | 98 +++++++++++++++++++++++ 5 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 token-server/tnc.html diff --git a/server/migrations/0001_key_data_table.sql b/server/migrations/0001_key_data_table.sql index 68b39bab..082df6cd 100644 --- a/server/migrations/0001_key_data_table.sql +++ b/server/migrations/0001_key_data_table.sql @@ -55,5 +55,6 @@ CREATE TABLE public.tokens ( onchain_address varchar NULL, processor_id varchar NULL, confirmed boolean DEFAULT false, - spent boolean DEFAULT false + spent boolean DEFAULT false, + accepted boolean DEFAULT false ); \ No newline at end of file diff --git a/token-server/src/endpoints/token.rs b/token-server/src/endpoints/token.rs index ce4795f4..1cb8d62b 100644 --- a/token-server/src/endpoints/token.rs +++ b/token-server/src/endpoints/token.rs @@ -120,6 +120,33 @@ pub async fn token_init(token_server: &State) -> status::Custom) -> status::Custom> { + + let token_id = uuid::Uuid::new_v4().to_string(); + + let invoice: Invoice = get_lightning_invoice(token_server, token_id.clone()).await; + + let pod_info = PODInfo { + token_id: token_id.clone(), + fee: token_server.config.fee.clone(), + lightning_invoice: invoice.pr.clone(), + btc_payment_address: invoice.onChainAddr.clone(), + processor_id: invoice.id.clone(), + }; + + insert_new_token(&token_server.pool, &token_id, &invoice.pr.clone(), &invoice.onChainAddr, &invoice.id).await; + + let config = crate::server_config::ServerConfig::load(); + + let response_body = json!({ + "pod_info": pod_info, + "tnc": config.tnc.clone(), + }); + + return status::Custom(Status::Ok, Json(response_body)); +} + #[get("/token/token_verify/")] pub async fn token_verify(token_server: &State, token_id: String) -> status::Custom> { diff --git a/token-server/src/main.rs b/token-server/src/main.rs index 044c1487..fca9dd92 100644 --- a/token-server/src/main.rs +++ b/token-server/src/main.rs @@ -35,6 +35,7 @@ async fn main() { .mount("/", routes![ endpoints::token::token_init, endpoints::token::token_verify, + endpoints::token::token_gen, ]) .register("/", catchers![ not_found, diff --git a/token-server/src/server_config.rs b/token-server/src/server_config.rs index eabe226c..df7d486c 100644 --- a/token-server/src/server_config.rs +++ b/token-server/src/server_config.rs @@ -1,6 +1,6 @@ use config::{Config as ConfigRs, Environment, File}; use serde::{Serialize, Deserialize}; -use std::env; +use std::{env, fs}; /// Config struct storing all StataChain Entity config #[derive(Debug, Serialize, Deserialize)] @@ -17,6 +17,8 @@ pub struct ServerConfig { pub delay: u64, /// Postgres connection string pub connection_string: String, + /// Tnc string + pub tnc: String, } impl Default for ServerConfig { @@ -28,6 +30,7 @@ impl Default for ServerConfig { fee: String::from("10000"), delay: 3600, connection_string: String::from("postgresql://postgres:postgres@localhost/mercury"), + tnc: fs::read_to_string("../tnc.html").unwrap_or_else(|_| String::from("")), } } } @@ -41,6 +44,7 @@ impl From for ServerConfig { fee: config.get::("fee").unwrap_or_else(|_| String::new()), delay: config.get::("delay").unwrap_or(0), connection_string: config.get::("connection_string").unwrap_or_else(|_| String::new()), + tnc: fs::read_to_string("../tnc.html").unwrap_or_else(|_| String::from("")), } } } @@ -73,6 +77,7 @@ impl ServerConfig { fee: get_env_or_config("fee", "FEE"), delay: get_env_or_config("delay", "DELAY").parse::().unwrap(), connection_string: get_env_or_config("connection_string", "CONNECTION_STRING"), + tnc: fs::read_to_string("../tnc.html").unwrap_or_else(|_| String::from("")), } } } diff --git a/token-server/tnc.html b/token-server/tnc.html new file mode 100644 index 00000000..680ae9aa --- /dev/null +++ b/token-server/tnc.html @@ -0,0 +1,98 @@ +
+ Terms of Use +

Users of Mercury Wallet should carefully read the terms of use detailed below. By clicking ‘Agree’ or by accessing or downloading our services a User agrees to be bound by these Terms of Use. These Terms of User are not assignable by the user to anyone else.

+
Definitions
+

"Coinswap Conductor Service" is a service that coordinates atomic statecoin swaps to prevent third parties from linking outputs on the public Bitcoin blockchain;

+

“Layer Two Limited” is a limited liability, International Business Company registered in the Republic of Seychelles. References to Layer Two Limited include references to its holding subsidiaries, affiliates, partners, agents, assignees, employees, licensors, service providers or subcontractors;

+

“Mercury Server” means the Statechain entity and the Coinswap Conductor Service;

+

“Mercury Software” means the software that creates the User’s Wallet and operates the Mercury Server (Statechain Entity and Swap Conductor);

+

“Mercury Wallet” means Mercury Wallet, its subsidiaries and affiliates as owned and operated by Layer Two Limited;

+

“Private Key” means the encrypted information stored locally on the User’s computer in a wallet file which enables access to the wallet;

+

“Recovery words” means those words automatically and randomly generated by the software upon the creation of the wallet for the securing access to the wallet;

+

“Password” means an additional word added optionally by the User for the purpose of recovery of the access to the Wallet;

+

“User” is the individual person or entity using the services provided by Layer Two Limited;

+

“User’s Wallet” is the software creating an individualised wallet application created specifically by and for the User enabling the User to access the Bitcoin network and the Mercury Server without the need or requirement to create or maintain a user account; and

+

“Wallet back up” means the combination of the recovery words and the password.

+
General
+

Layer Two Limited provides, markets and operates Mercury Wallet, offering a freely downloadable, open-source desktop Bitcoin wallet under the GNU General Public License.

+
Application
+

These terms and conditions apply to all use of the services provided by Layer Two Limited. These Terms of Use apply to the download of the User Wallet, any access and use of the User Wallet and Mercury Software, the website at https://mercurywallet.com or its onion mirror at http://mercury32vj43p4ychitp5qgqbcwmz36alalpd76nma3zbcedjmgyoqd.onion and its Statechain Entity and Conductor services (as defined below), and any of the other Services related to or utilizing any of the foregoing, which are referred to in these “Terms of Use” as the “Mercury Services” or “Services”.

+
Security and User responsibility
+

All services provided by Mercury Wallet are on a non-custodial basis. Layer Two Limited and the Mercury Software does not have access to, or the ability to decrypt a User’s Wallet. Only the user can decrypt their stored information in the User Wallet.

+

Layer Two Limited does not keep or store User’s keys. The safekeeping of User’s keys is the sole responsibility of the User.

+

Layer Two Limited will not ask for recovery words, passwords or similar security-related information. Users should never provide any security-critical information to any person purporting to represent Layer Two Limited, its affiliates or partners.

+

The User’s Wallet and the Mercury Server perform timelocked backup transactions automatically. The user bears the sole responsibility for performing the broadcast of such transactions. Layer Two Limited will not be held responsible for failures to perform this function on time.

+

Users use this service in their own discretion and in compliance with all applicable laws and regulations. Users assume full responsibility for the consequences of their use of the service, including the safekeeping of their recovery words, passwords and stored keys, and user uses the services at their own risk.

+

Layer Two Limited is unable to monitor or regulate the User’s use of the services.

+
User warranties
+

The User confirms and warrants that:

+
    +
  • Where they are representing a legal entity or company, that they have the authorisation and power to bind the legal entity or company to the terms of service agreement and/or to use this service on behalf of that entity or company.
  • +
  • That they have legal capacity to accept these terms and conditions and enter into this agreement. The Software is not available to persons under the age of 18 years old. Users who do not qualify are not permitted to use the Mercury Software unless specifically permitted to contract under their applicable domestic law.
  • +
  • That they have legal capacity to enter into the transactions using the Mercury Wallet.
  • +
  • They are using the services in compliance with their own local laws and jurisdiction.
  • +
  • The user is aware that national taxation laws may apply to Bitcoin transactions. The User undertakes sole responsibility for determining, calculating and paying any taxes or duties applicable to their transactions under the laws or regulations applicable to their use of the service. Layer Two Limited will not calculate, determine, pay, collect any revenue on behalf of any national government or user.
  • +
  • Users are aware that investment in Bitcoin can lead to loss of money over time. Layer Two Limited will not be held liable for damages or loss due to the fluctuations in the value of Bitcoin.
  • +
  • Users assume use of the service at their own risk. Layer Two Limited is not liable for the actions, decisions or other behaviour of the user taken in reliance on information provided by third party services.
  • +
+
Reference information on Mercury Wallet website
+

Mercury Wallet provides reference information of a general nature on its website. The information that is provided by Layer Two Limited is not intended to replace professional legal, financial or investment advice.

+

Any indicative exchange prices displayed on the website are provided by third party services and not by Mercury Wallet itself. Layer Two Limited is not liable for reliance on information provided by third party services.

+
Provisions related to Bitcoin
+

Layer Two Limited makes no guarantees that Bitcoins can be exchanged, sold or traded at the price displayed by indicative third party services.

+

Layer Two Limited has no control over the value of Bitcoin or the operation of the underlying software protocols which govern the operation of Bitcoin.

+

Layer Two Limited is not responsible for the functioning of the underlying software protocols which govern the operation of Bitcoin and does not guarantee their functionality, security or availability. Layer Two Limited will not be liable for any loss or damages incurred as a result of the failure or inaccessibility of the underlying protocols.

+
Force Majeure and Acts of God
+

Layer Two Limited and the User agree to not hold liable the other party for any breach of this agreement due to inability to perform as a result of an act of God or an inevitable accident or other events out of the control of the parties, including but not limited to fires, telecommunication interruptions, utility or power failures, equipment failures, labour strikes, riots, war, non-performance of vendors or suppliers, or other causes over which the respective party have no reasonable control, provided that the party concerned has procedures in place to avoid the effects of such events.

+

Damages or losses arising from situations of impossibility to perform under this agreement will be borne by the parties individually.

+
Accessing the wallet
+

The User is granted sole access to its User Wallet which is enabled through the use of recovery words, passwords and encrypted secret keys.

+

Layer Two Limited does not store or otherwise have access to the recovery words, passwords or Private Keys and cannot recover the Wallet Backup in the event of loss of it by the User.

+

The User is solely responsible for ensuring that the Wallet Backup and all passwords are secure. The User should not share this information with any person.

+

Layer Two Limited is not able to restore access to the wallet in any circumstances upon the loss of the Wallet back up.

+

Layer Two Limited is not liable for any losses arising as a result of the User losing access to the wallet for any reason, including the loss of Bitcoin in a wallet occurring due to loss or theft of the Private Key, Password, or Wallet back up.

+
Prohibited Activities
+

Notwithstanding the generality of the foregoing, the User agrees to use Mercury Software in a lawful manner and to refrain from any activity which hinders or otherwise adversely affects the performance of or the provision by Layer Two Limited of its services to the User or any other users.

+

The User undertakes not to "Reverse Engineer", change, modify, hack, translate, copy, distribute, pledge, assign, transfer, make derivative works, exploit, encumber or crack any portion of the Software.

+

The User specifically agrees to defend, indemnify and hold harmless Layer Two Limited against any and all claims, costs, losses, damages, liability, judgments and expenses (including without limitation costs and reasonable attorneys’ fees) in connection with or arising from or in any way related to the use of the Mercury Software by the User in breach of these Terms of Use or use of the Mercury Software.

+

The User undertakes to inform Layer Two Limited immediately, or as early as possible, of any use of the Mercury Software by it, whether advertent or inadvertent which may negatively affect the rights of or cause any loss or damage to, any other person or entity.

+
Fees for services
+

The User will not be charged by Layer Two Limited for downloading the User Wallet, depositing Bitcoin, or transactions of statecoins on the Mercury Server.

+

The User will be liable for transactions fees charged by the Bitcoin network, a third party separate of Layer Two Limited. The User authorises the wallet to automatically deduct transaction fees from the User’s withdrawal amount and transmit the same amount to the Bitcoin network.

+

A percentage fee is only charged by Layer Two Limited upon withdrawal from the service to a third-party wallet, regardless of the number of transfers or coinswaps performed using the Mercury Software.

+

The User acknowledges full knowledge that a transaction fee of 0.5% (point five percent) of the value of the deposit into the wallet is due and payable upon the withdrawal of the Bitcoin from the User Wallet. The User authorises Layer Two Limited to automatically deduct the transaction fees from the value of the Bitcoin on the withdrawal from the wallet.

+

Layer Two Limited reserves the right to alter the percentage charged to the User or to change the fees payable by the User for the services provided by Mercury Wallet with 30 days advance notice of any such chance. Notice will be in writing, published on this website and all best efforts will be undertaken to ensure that the User has knowledge of the change of fees applicable.

+
Inapplicability of financial regulation law
+

Layer Two Limited is not a financial institution for the purposes of the Seychelles Financial Institutions Act 14 of 2004 as amended or any other statue so regulations and does not provide banking services to the User.

+

Layer Two Limited does not perform any acts as a bank, including but not limited to receiving money deposits, extending credit facilities, investment of own or User funds, buying and selling money market instruments, providing money transmission services, buying and selling foreign currency, issuing and administering means of payment, money brokering, safekeeping and administration of valuables, providing portfolio management or advice or in any other way acting as a custodian, possessor or guardian, exchange or financial intermediary of or for the User’s Bitcoins.

+

The User Wallet enables coins to be transferred between owners via the Mercury Server, however, the Mercury Server does not have control or custody over the funds and does not possess, store or transmit value belonging to others.

+

The User accepts full knowledge that Layer Two Limited is not performing the functions of a financial institution or bank and that the transactions undertaken using the Mercury Software are exempt from the provisions of law applying to financial institutions.

+
Intellectual Property Rights
+

The Mercury Software is open-sourcse under the GNU license and permission is hereby granted free of charge, to any person obtaining a copy of this software and associated documentation files to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

+

The User cedes full ownership to any feedback that it provides on the Mercury Wallet services to Layer Two Limited, including the suggestion of content, features or documents. This feedback is non-confidential and shall become the sole property of Layer Two Limited to use or develop without restriction.

+

All trademarks, servicemarks, designs, logos, URLs and trade names including by not limited to ‘Mercury Wallet’, ‘Mercury Server’ and ‘Layer Two Limited’ that are displayed on the Mercury Wallet services are granted to the User on a limited, non-exclusive, revocable, royalty free, non-transferable, non-sublicenceable licence to access and use in relation to the use of the Mercury Software.

+

The User accepts full knowledge that Layer Two Limited is not performing the functions of a financial institution or bank and that the transactions undertaken using the Mercury Software are exempt from the provisions of law applying to financial institutions.

+
Disclaimer of warranties and representations
+

Save as contained in the provisions of this Terms of Use Agreement, use of the Mercury Software by the User is voluntary and without any reliance on warranty, representation or undertaking of any type.

+

Except to the extent that these have been specifically reduced to writing in this Terms of Use Agreement, Layer Two Limited disclaims all warranties, representation and conditions relating to the use of the Mercury Software. It further disclaims any implied warranties relating to title, non-infringement, merchantability and fitness for a particular purpose.

+
Assumption of liability
+

The User assumes the full risk and conditions of liability attaching to the use of the Mercury Software.

+

TO THE MAXIMUM EXTENT PERMITTED BY LAW, UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, DELICT/TORT, CONTRACT OR OTHERWISE, SHALL LAYER TWO LIMITED, MERCURY WALLET OR ANY OF ITS UNDERLYING SERVICE PROVIDERS, BUSINESS PARTNERS, INFORMATION PROVIDERS, ACCOUNT PROVIDERS, LICENSORS, OFFICERS, DIRECTORS, EMPLOYEES, DISTRIBUTORS OR AGENTS; BE LIABLE TO THE USER OR ANY OTHER PERSON FOR ANY MONEY DAMAGES, WHETHER DIRECT, INDIRECT, SPECIAL, INCIDENTAL, COVER, RELIANCE OR CONSEQUENTIAL DAMAGES, EVEN IF LAYER TWO LIMITED SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.

+

IN THE EVENT THAT, NOTWITHSTANDING THE FOREGOING, LAYER TWO LIMITED IS FOUND LIABLE TO THE USER FOR DAMAGES FROM ANY CAUSE WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION [WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), DELICT, SOFTWARE LIABILITY OR OTHERWISE], THE MAXIMUM AGGREGATE LIABILITY OF LAYER TWO LIMITED TO THE USER ARISING IN CONNECTION WITH THIS AGREEMENT SHALL BE LIMITED TO THE AMOUNT THE USER PAID FOR THE SOFTWARE IN THE TWELVE (12) MONTHS PRIOR TO THE ACCRUAL OF THE APPLICABLE CLAIM, LESS ANY DAMAGES PREVIOUSLY PAID BY LAYER TWO LIMITED TO THE USER IN THAT TWELVE (12) MONTH PERIOD.

+
Links to Third-Party Websites
+

Mercury Website provides users links to third-party websites. These links are provided to users as a convenience, and Layer Two Limited is not responsible for the content of any linked website. Any non-Layer Two Limited website accessed from this website is independent from Layer Two Limited, and Layer Two Limited has no control over the content of that website. In addition, a link to any non-Layer Two Limited website does not imply that Layer Two Limited endorses or accepts any responsibility for the content or use of such website.

+
Entire Agreement
+

These Terms of Use constitute the entire agreement (complete and exclusive) between Layer Two Limited and the User and supersede or replace any previous or contemporaneous terms or agreements, representations, warranties or understandings, whether written or oral.

+

If any provision of the Agreement is found to be unenforceable or invalid, that provision will be limited or eliminated to the minimum extent necessary so that this Agreement will otherwise remain in full force, in effect and enforceable.

+
Assignment
+

The rights and obligations arising under these Terms and Conditions may be assigned to and become binding on the parties’ parent companies, subsidiaries, or legal affiliates and will survive a merger, consolidation, or sale of Layer Two Limited’s assets.

+
No waiver
+

Delayed, late or failed performance by Layer Two Limited to exercise or enforce any right or remedy (or any part thereof) accruing to it under these Terms of Use or by law does not constated a waiver of that or any other right or remedy. Layer Two Limited will not be precluded from further exercising that or any other lawful right or remedy.

+
Governing law and choice of jurisdiction
+

Any dispute or claim arising out of or in connection with the use of Layer Two Limited’s services, including disputes related to or arising from these Terms of Use, shall be governed exclusively by Seychellois law and the courts of Seychelles shall have exclusive jurisdiction to hear and determine any such disputes or claims.

+

Layer Two Limited will not be held liable for actions of its users in breach of foreign laws. End users are solely responsible for ensuring that they comply with the laws of the country in which they are resident, domiciled or otherwise present.

+
Privacy Policy
+

Layer Two Limited’s Privacy Policy is located at (link). By using Mercury Software, the User accepts and agrees to all terms, provisions, and conditions of the Privacy Policy.

+
Additional Information
+

If you have any questions about the use of Mercury Wallet or these Terms of Use, please contact us at (hyperlink applicable email address and physical address for contact)

+
\ No newline at end of file From 955e083e35b68b52b4513b4f1578a9ad19444bf9 Mon Sep 17 00:00:00 2001 From: DhananjayPurohit Date: Fri, 30 Aug 2024 08:16:08 +0530 Subject: [PATCH 2/7] feat: add endpoint for tnc acceptance --- docker-compose-test.yml | 16 ++++++++++++++++ token-server/src/endpoints/token.rs | 29 +++++++++++++++++++++++++++++ token-server/src/main.rs | 1 + 3 files changed, 46 insertions(+) diff --git a/docker-compose-test.yml b/docker-compose-test.yml index c629574c..63bcd5ac 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -70,6 +70,22 @@ services: depends_on: - postgres + token-server: + build: + context: . + dockerfile: ./token-server/Dockerfile + environment: + PROCESSOR_URL: http://mercurylayer-enclave-sgx-1:18080" + API_KEY: aaaaa + FEE: 10000 + UNIT: BTC + DELAY: 3600 + CONNECTION_STRING: postgres://postgres:pgpassword@postgres:5432/postgres + ports: + - "8001:8001" + depends_on: + - postgres + alice: image: lightninglabs/lndinit:v0.1.21-beta-lnd-v0.18.0-beta container_name: mercurylayer-alice-1 diff --git a/token-server/src/endpoints/token.rs b/token-server/src/endpoints/token.rs index 1cb8d62b..95f5a61f 100644 --- a/token-server/src/endpoints/token.rs +++ b/token-server/src/endpoints/token.rs @@ -147,6 +147,18 @@ pub async fn token_gen(token_server: &State) -> status::Custom")] +pub async fn token_accept(token_server: &State, token_id: String) -> status::Custom> { + + set_tnc_accepted(&token_server.pool, &token_id).await; + + let response_body = json!({ + "accepted": true, + }); + + return status::Custom(Status::Ok, Json(response_body)); +} + #[get("/token/token_verify/")] pub async fn token_verify(token_server: &State, token_id: String) -> status::Custom> { @@ -291,3 +303,20 @@ pub async fn set_token_confirmed(pool: &sqlx::PgPool, token_id: &str) { transaction.commit().await.unwrap(); } + +pub async fn set_tnc_accepted(pool: &sqlx::PgPool, token_id: &str) { + + let mut transaction = pool.begin().await.unwrap(); + + let query = "UPDATE tokens \ + SET accepted = true \ + WHERE token_id = $1"; + + let _ = sqlx::query(query) + .bind(token_id) + .execute(&mut *transaction) + .await + .unwrap(); + + transaction.commit().await.unwrap(); +} diff --git a/token-server/src/main.rs b/token-server/src/main.rs index fca9dd92..c603d8b9 100644 --- a/token-server/src/main.rs +++ b/token-server/src/main.rs @@ -36,6 +36,7 @@ async fn main() { endpoints::token::token_init, endpoints::token::token_verify, endpoints::token::token_gen, + endpoints::token::token_accept, ]) .register("/", catchers![ not_found, From 7b836e70371909fbe6d56d2b6271d04a27aea298 Mon Sep 17 00:00:00 2001 From: DhananjayPurohit Date: Wed, 4 Sep 2024 20:46:26 +0530 Subject: [PATCH 3/7] fix: token init for tnc acceptance --- docker-compose-test.yml | 6 ++--- token-server/src/endpoints/token.rs | 39 +++++++++++++---------------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/docker-compose-test.yml b/docker-compose-test.yml index 63bcd5ac..f7b8e847 100644 --- a/docker-compose-test.yml +++ b/docker-compose-test.yml @@ -75,9 +75,9 @@ services: context: . dockerfile: ./token-server/Dockerfile environment: - PROCESSOR_URL: http://mercurylayer-enclave-sgx-1:18080" - API_KEY: aaaaa - FEE: 10000 + PROCESSOR_URL: https://api.swiss-bitcoin-pay.ch + API_KEY: aaaa + FEE: 0.0001 UNIT: BTC DELAY: 3600 CONNECTION_STRING: postgres://postgres:pgpassword@postgres:5432/postgres diff --git a/token-server/src/endpoints/token.rs b/token-server/src/endpoints/token.rs index 95f5a61f..7544b0b4 100644 --- a/token-server/src/endpoints/token.rs +++ b/token-server/src/endpoints/token.rs @@ -99,22 +99,29 @@ pub struct PODStatus { } -#[get("/token/token_init")] -pub async fn token_init(token_server: &State) -> status::Custom> { +#[get("/token/token_init/")] +pub async fn token_init(token_server: &State, token_id: String) -> status::Custom> { - let token_id = uuid::Uuid::new_v4().to_string(); + set_tnc_accepted(&token_server.pool, &token_id).await; + + let row = sqlx::query( + "SELECT token_id, invoice, onchain_address, processor_id \ + FROM public.tokens \ + WHERE token_id = $1") + .bind(&token_id) + .fetch_one(&token_server.pool) + .await; + + let row = row.unwrap(); - let invoice: Invoice = get_lightning_invoice(token_server, token_id.clone()).await; let pod_info = PODInfo { - token_id: token_id.clone(), + token_id: row.get(0), fee: token_server.config.fee.clone(), - lightning_invoice: invoice.pr.clone(), - btc_payment_address: invoice.onChainAddr.clone(), - processor_id: invoice.id.clone(), + lightning_invoice: row.get(1), + btc_payment_address: row.get(2), + processor_id: row.get(3), }; - insert_new_token(&token_server.pool, &token_id, &invoice.pr.clone(), &invoice.onChainAddr, &invoice.id).await; - let response_body = json!(pod_info); return status::Custom(Status::Ok, Json(response_body)); @@ -147,18 +154,6 @@ pub async fn token_gen(token_server: &State) -> status::Custom")] -pub async fn token_accept(token_server: &State, token_id: String) -> status::Custom> { - - set_tnc_accepted(&token_server.pool, &token_id).await; - - let response_body = json!({ - "accepted": true, - }); - - return status::Custom(Status::Ok, Json(response_body)); -} - #[get("/token/token_verify/")] pub async fn token_verify(token_server: &State, token_id: String) -> status::Custom> { From a5fad6a6132db2fa0a8f5217b80c9baf7331278d Mon Sep 17 00:00:00 2001 From: DhananjayPurohit Date: Thu, 5 Sep 2024 16:45:30 +0530 Subject: [PATCH 4/7] fix: dir for tnc.html --- token-server/src/main.rs | 1 - token-server/src/server_config.rs | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/token-server/src/main.rs b/token-server/src/main.rs index c603d8b9..fca9dd92 100644 --- a/token-server/src/main.rs +++ b/token-server/src/main.rs @@ -36,7 +36,6 @@ async fn main() { endpoints::token::token_init, endpoints::token::token_verify, endpoints::token::token_gen, - endpoints::token::token_accept, ]) .register("/", catchers![ not_found, diff --git a/token-server/src/server_config.rs b/token-server/src/server_config.rs index df7d486c..43363ef2 100644 --- a/token-server/src/server_config.rs +++ b/token-server/src/server_config.rs @@ -30,7 +30,7 @@ impl Default for ServerConfig { fee: String::from("10000"), delay: 3600, connection_string: String::from("postgresql://postgres:postgres@localhost/mercury"), - tnc: fs::read_to_string("../tnc.html").unwrap_or_else(|_| String::from("")), + tnc: fs::read_to_string("tnc.html").unwrap_or_else(|_| String::from("")), } } } @@ -44,7 +44,7 @@ impl From for ServerConfig { fee: config.get::("fee").unwrap_or_else(|_| String::new()), delay: config.get::("delay").unwrap_or(0), connection_string: config.get::("connection_string").unwrap_or_else(|_| String::new()), - tnc: fs::read_to_string("../tnc.html").unwrap_or_else(|_| String::from("")), + tnc: fs::read_to_string("tnc.html").unwrap_or_else(|_| String::from("")), } } } @@ -77,7 +77,7 @@ impl ServerConfig { fee: get_env_or_config("fee", "FEE"), delay: get_env_or_config("delay", "DELAY").parse::().unwrap(), connection_string: get_env_or_config("connection_string", "CONNECTION_STRING"), - tnc: fs::read_to_string("../tnc.html").unwrap_or_else(|_| String::from("")), + tnc: fs::read_to_string("tnc.html").unwrap_or_else(|_| String::from("")), } } } From 2535bd37f20856314adfa8c214c1dae3a2bff4ce Mon Sep 17 00:00:00 2001 From: Tom Trevethan Date: Thu, 5 Sep 2024 23:08:39 +0100 Subject: [PATCH 5/7] Update tnc.html (#92) --- token-server/tnc.html | 182 +++++++++++++++++++----------------------- 1 file changed, 84 insertions(+), 98 deletions(-) diff --git a/token-server/tnc.html b/token-server/tnc.html index 680ae9aa..13721532 100644 --- a/token-server/tnc.html +++ b/token-server/tnc.html @@ -1,98 +1,84 @@ -
- Terms of Use -

Users of Mercury Wallet should carefully read the terms of use detailed below. By clicking ‘Agree’ or by accessing or downloading our services a User agrees to be bound by these Terms of Use. These Terms of User are not assignable by the user to anyone else.

-
Definitions
-

"Coinswap Conductor Service" is a service that coordinates atomic statecoin swaps to prevent third parties from linking outputs on the public Bitcoin blockchain;

-

“Layer Two Limited” is a limited liability, International Business Company registered in the Republic of Seychelles. References to Layer Two Limited include references to its holding subsidiaries, affiliates, partners, agents, assignees, employees, licensors, service providers or subcontractors;

-

“Mercury Server” means the Statechain entity and the Coinswap Conductor Service;

-

“Mercury Software” means the software that creates the User’s Wallet and operates the Mercury Server (Statechain Entity and Swap Conductor);

-

“Mercury Wallet” means Mercury Wallet, its subsidiaries and affiliates as owned and operated by Layer Two Limited;

-

“Private Key” means the encrypted information stored locally on the User’s computer in a wallet file which enables access to the wallet;

-

“Recovery words” means those words automatically and randomly generated by the software upon the creation of the wallet for the securing access to the wallet;

-

“Password” means an additional word added optionally by the User for the purpose of recovery of the access to the Wallet;

-

“User” is the individual person or entity using the services provided by Layer Two Limited;

-

“User’s Wallet” is the software creating an individualised wallet application created specifically by and for the User enabling the User to access the Bitcoin network and the Mercury Server without the need or requirement to create or maintain a user account; and

-

“Wallet back up” means the combination of the recovery words and the password.

-
General
-

Layer Two Limited provides, markets and operates Mercury Wallet, offering a freely downloadable, open-source desktop Bitcoin wallet under the GNU General Public License.

-
Application
-

These terms and conditions apply to all use of the services provided by Layer Two Limited. These Terms of Use apply to the download of the User Wallet, any access and use of the User Wallet and Mercury Software, the website at https://mercurywallet.com or its onion mirror at http://mercury32vj43p4ychitp5qgqbcwmz36alalpd76nma3zbcedjmgyoqd.onion and its Statechain Entity and Conductor services (as defined below), and any of the other Services related to or utilizing any of the foregoing, which are referred to in these “Terms of Use” as the “Mercury Services” or “Services”.

-
Security and User responsibility
-

All services provided by Mercury Wallet are on a non-custodial basis. Layer Two Limited and the Mercury Software does not have access to, or the ability to decrypt a User’s Wallet. Only the user can decrypt their stored information in the User Wallet.

-

Layer Two Limited does not keep or store User’s keys. The safekeeping of User’s keys is the sole responsibility of the User.

-

Layer Two Limited will not ask for recovery words, passwords or similar security-related information. Users should never provide any security-critical information to any person purporting to represent Layer Two Limited, its affiliates or partners.

-

The User’s Wallet and the Mercury Server perform timelocked backup transactions automatically. The user bears the sole responsibility for performing the broadcast of such transactions. Layer Two Limited will not be held responsible for failures to perform this function on time.

-

Users use this service in their own discretion and in compliance with all applicable laws and regulations. Users assume full responsibility for the consequences of their use of the service, including the safekeeping of their recovery words, passwords and stored keys, and user uses the services at their own risk.

-

Layer Two Limited is unable to monitor or regulate the User’s use of the services.

-
User warranties
-

The User confirms and warrants that:

-
    -
  • Where they are representing a legal entity or company, that they have the authorisation and power to bind the legal entity or company to the terms of service agreement and/or to use this service on behalf of that entity or company.
  • -
  • That they have legal capacity to accept these terms and conditions and enter into this agreement. The Software is not available to persons under the age of 18 years old. Users who do not qualify are not permitted to use the Mercury Software unless specifically permitted to contract under their applicable domestic law.
  • -
  • That they have legal capacity to enter into the transactions using the Mercury Wallet.
  • -
  • They are using the services in compliance with their own local laws and jurisdiction.
  • -
  • The user is aware that national taxation laws may apply to Bitcoin transactions. The User undertakes sole responsibility for determining, calculating and paying any taxes or duties applicable to their transactions under the laws or regulations applicable to their use of the service. Layer Two Limited will not calculate, determine, pay, collect any revenue on behalf of any national government or user.
  • -
  • Users are aware that investment in Bitcoin can lead to loss of money over time. Layer Two Limited will not be held liable for damages or loss due to the fluctuations in the value of Bitcoin.
  • -
  • Users assume use of the service at their own risk. Layer Two Limited is not liable for the actions, decisions or other behaviour of the user taken in reliance on information provided by third party services.
  • -
-
Reference information on Mercury Wallet website
-

Mercury Wallet provides reference information of a general nature on its website. The information that is provided by Layer Two Limited is not intended to replace professional legal, financial or investment advice.

-

Any indicative exchange prices displayed on the website are provided by third party services and not by Mercury Wallet itself. Layer Two Limited is not liable for reliance on information provided by third party services.

-
Provisions related to Bitcoin
-

Layer Two Limited makes no guarantees that Bitcoins can be exchanged, sold or traded at the price displayed by indicative third party services.

-

Layer Two Limited has no control over the value of Bitcoin or the operation of the underlying software protocols which govern the operation of Bitcoin.

-

Layer Two Limited is not responsible for the functioning of the underlying software protocols which govern the operation of Bitcoin and does not guarantee their functionality, security or availability. Layer Two Limited will not be liable for any loss or damages incurred as a result of the failure or inaccessibility of the underlying protocols.

-
Force Majeure and Acts of God
-

Layer Two Limited and the User agree to not hold liable the other party for any breach of this agreement due to inability to perform as a result of an act of God or an inevitable accident or other events out of the control of the parties, including but not limited to fires, telecommunication interruptions, utility or power failures, equipment failures, labour strikes, riots, war, non-performance of vendors or suppliers, or other causes over which the respective party have no reasonable control, provided that the party concerned has procedures in place to avoid the effects of such events.

-

Damages or losses arising from situations of impossibility to perform under this agreement will be borne by the parties individually.

-
Accessing the wallet
-

The User is granted sole access to its User Wallet which is enabled through the use of recovery words, passwords and encrypted secret keys.

-

Layer Two Limited does not store or otherwise have access to the recovery words, passwords or Private Keys and cannot recover the Wallet Backup in the event of loss of it by the User.

-

The User is solely responsible for ensuring that the Wallet Backup and all passwords are secure. The User should not share this information with any person.

-

Layer Two Limited is not able to restore access to the wallet in any circumstances upon the loss of the Wallet back up.

-

Layer Two Limited is not liable for any losses arising as a result of the User losing access to the wallet for any reason, including the loss of Bitcoin in a wallet occurring due to loss or theft of the Private Key, Password, or Wallet back up.

-
Prohibited Activities
-

Notwithstanding the generality of the foregoing, the User agrees to use Mercury Software in a lawful manner and to refrain from any activity which hinders or otherwise adversely affects the performance of or the provision by Layer Two Limited of its services to the User or any other users.

-

The User undertakes not to "Reverse Engineer", change, modify, hack, translate, copy, distribute, pledge, assign, transfer, make derivative works, exploit, encumber or crack any portion of the Software.

-

The User specifically agrees to defend, indemnify and hold harmless Layer Two Limited against any and all claims, costs, losses, damages, liability, judgments and expenses (including without limitation costs and reasonable attorneys’ fees) in connection with or arising from or in any way related to the use of the Mercury Software by the User in breach of these Terms of Use or use of the Mercury Software.

-

The User undertakes to inform Layer Two Limited immediately, or as early as possible, of any use of the Mercury Software by it, whether advertent or inadvertent which may negatively affect the rights of or cause any loss or damage to, any other person or entity.

-
Fees for services
-

The User will not be charged by Layer Two Limited for downloading the User Wallet, depositing Bitcoin, or transactions of statecoins on the Mercury Server.

-

The User will be liable for transactions fees charged by the Bitcoin network, a third party separate of Layer Two Limited. The User authorises the wallet to automatically deduct transaction fees from the User’s withdrawal amount and transmit the same amount to the Bitcoin network.

-

A percentage fee is only charged by Layer Two Limited upon withdrawal from the service to a third-party wallet, regardless of the number of transfers or coinswaps performed using the Mercury Software.

-

The User acknowledges full knowledge that a transaction fee of 0.5% (point five percent) of the value of the deposit into the wallet is due and payable upon the withdrawal of the Bitcoin from the User Wallet. The User authorises Layer Two Limited to automatically deduct the transaction fees from the value of the Bitcoin on the withdrawal from the wallet.

-

Layer Two Limited reserves the right to alter the percentage charged to the User or to change the fees payable by the User for the services provided by Mercury Wallet with 30 days advance notice of any such chance. Notice will be in writing, published on this website and all best efforts will be undertaken to ensure that the User has knowledge of the change of fees applicable.

-
Inapplicability of financial regulation law
-

Layer Two Limited is not a financial institution for the purposes of the Seychelles Financial Institutions Act 14 of 2004 as amended or any other statue so regulations and does not provide banking services to the User.

-

Layer Two Limited does not perform any acts as a bank, including but not limited to receiving money deposits, extending credit facilities, investment of own or User funds, buying and selling money market instruments, providing money transmission services, buying and selling foreign currency, issuing and administering means of payment, money brokering, safekeeping and administration of valuables, providing portfolio management or advice or in any other way acting as a custodian, possessor or guardian, exchange or financial intermediary of or for the User’s Bitcoins.

-

The User Wallet enables coins to be transferred between owners via the Mercury Server, however, the Mercury Server does not have control or custody over the funds and does not possess, store or transmit value belonging to others.

-

The User accepts full knowledge that Layer Two Limited is not performing the functions of a financial institution or bank and that the transactions undertaken using the Mercury Software are exempt from the provisions of law applying to financial institutions.

-
Intellectual Property Rights
-

The Mercury Software is open-sourcse under the GNU license and permission is hereby granted free of charge, to any person obtaining a copy of this software and associated documentation files to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

-

The User cedes full ownership to any feedback that it provides on the Mercury Wallet services to Layer Two Limited, including the suggestion of content, features or documents. This feedback is non-confidential and shall become the sole property of Layer Two Limited to use or develop without restriction.

-

All trademarks, servicemarks, designs, logos, URLs and trade names including by not limited to ‘Mercury Wallet’, ‘Mercury Server’ and ‘Layer Two Limited’ that are displayed on the Mercury Wallet services are granted to the User on a limited, non-exclusive, revocable, royalty free, non-transferable, non-sublicenceable licence to access and use in relation to the use of the Mercury Software.

-

The User accepts full knowledge that Layer Two Limited is not performing the functions of a financial institution or bank and that the transactions undertaken using the Mercury Software are exempt from the provisions of law applying to financial institutions.

-
Disclaimer of warranties and representations
-

Save as contained in the provisions of this Terms of Use Agreement, use of the Mercury Software by the User is voluntary and without any reliance on warranty, representation or undertaking of any type.

-

Except to the extent that these have been specifically reduced to writing in this Terms of Use Agreement, Layer Two Limited disclaims all warranties, representation and conditions relating to the use of the Mercury Software. It further disclaims any implied warranties relating to title, non-infringement, merchantability and fitness for a particular purpose.

-
Assumption of liability
-

The User assumes the full risk and conditions of liability attaching to the use of the Mercury Software.

-

TO THE MAXIMUM EXTENT PERMITTED BY LAW, UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, DELICT/TORT, CONTRACT OR OTHERWISE, SHALL LAYER TWO LIMITED, MERCURY WALLET OR ANY OF ITS UNDERLYING SERVICE PROVIDERS, BUSINESS PARTNERS, INFORMATION PROVIDERS, ACCOUNT PROVIDERS, LICENSORS, OFFICERS, DIRECTORS, EMPLOYEES, DISTRIBUTORS OR AGENTS; BE LIABLE TO THE USER OR ANY OTHER PERSON FOR ANY MONEY DAMAGES, WHETHER DIRECT, INDIRECT, SPECIAL, INCIDENTAL, COVER, RELIANCE OR CONSEQUENTIAL DAMAGES, EVEN IF LAYER TWO LIMITED SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.

-

IN THE EVENT THAT, NOTWITHSTANDING THE FOREGOING, LAYER TWO LIMITED IS FOUND LIABLE TO THE USER FOR DAMAGES FROM ANY CAUSE WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION [WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), DELICT, SOFTWARE LIABILITY OR OTHERWISE], THE MAXIMUM AGGREGATE LIABILITY OF LAYER TWO LIMITED TO THE USER ARISING IN CONNECTION WITH THIS AGREEMENT SHALL BE LIMITED TO THE AMOUNT THE USER PAID FOR THE SOFTWARE IN THE TWELVE (12) MONTHS PRIOR TO THE ACCRUAL OF THE APPLICABLE CLAIM, LESS ANY DAMAGES PREVIOUSLY PAID BY LAYER TWO LIMITED TO THE USER IN THAT TWELVE (12) MONTH PERIOD.

-
Links to Third-Party Websites
-

Mercury Website provides users links to third-party websites. These links are provided to users as a convenience, and Layer Two Limited is not responsible for the content of any linked website. Any non-Layer Two Limited website accessed from this website is independent from Layer Two Limited, and Layer Two Limited has no control over the content of that website. In addition, a link to any non-Layer Two Limited website does not imply that Layer Two Limited endorses or accepts any responsibility for the content or use of such website.

-
Entire Agreement
-

These Terms of Use constitute the entire agreement (complete and exclusive) between Layer Two Limited and the User and supersede or replace any previous or contemporaneous terms or agreements, representations, warranties or understandings, whether written or oral.

-

If any provision of the Agreement is found to be unenforceable or invalid, that provision will be limited or eliminated to the minimum extent necessary so that this Agreement will otherwise remain in full force, in effect and enforceable.

-
Assignment
-

The rights and obligations arising under these Terms and Conditions may be assigned to and become binding on the parties’ parent companies, subsidiaries, or legal affiliates and will survive a merger, consolidation, or sale of Layer Two Limited’s assets.

-
No waiver
-

Delayed, late or failed performance by Layer Two Limited to exercise or enforce any right or remedy (or any part thereof) accruing to it under these Terms of Use or by law does not constated a waiver of that or any other right or remedy. Layer Two Limited will not be precluded from further exercising that or any other lawful right or remedy.

-
Governing law and choice of jurisdiction
-

Any dispute or claim arising out of or in connection with the use of Layer Two Limited’s services, including disputes related to or arising from these Terms of Use, shall be governed exclusively by Seychellois law and the courts of Seychelles shall have exclusive jurisdiction to hear and determine any such disputes or claims.

-

Layer Two Limited will not be held liable for actions of its users in breach of foreign laws. End users are solely responsible for ensuring that they comply with the laws of the country in which they are resident, domiciled or otherwise present.

-
Privacy Policy
-

Layer Two Limited’s Privacy Policy is located at (link). By using Mercury Software, the User accepts and agrees to all terms, provisions, and conditions of the Privacy Policy.

-
Additional Information
-

If you have any questions about the use of Mercury Wallet or these Terms of Use, please contact us at (hyperlink applicable email address and physical address for contact)

-
\ No newline at end of file +Users of the api.mercurylayer.com blind key service should carefully read the terms of use detailed below. By completing token_init with the supplied token_id or accessing our services a User agrees to be bound by these Terms of Use. These Terms of User are not assignable by the user to anyone else. + +Mercury layer is an implementation of a system the uses a blind co-signing and key-update service that enables statechains. +The Mercury blind key service generates and updates key shares (or key fragments) on request in addition to a count of partial blinded signatures. The blind key-update server never has control or custody, and is never aware of the identity of any shared key. + +Mercury layer service +The mercury layer service generates a private key share s1 on initialisation of a session. In order to initialise a session, a client must provide a valid token_id which controls access to the service. + +The client then initialises a session with an auth_pubkey which is used to authenticate all subsequent messages with the server. The server responds with the public elliptic curve point corresponding to the session private key share s1. + +Once initialised, the server can then perform two operations using the key share: + +Partial signature generation - the server uses the key share to compute a partial signature from a blinded challenge value provided by the client. +Key update - an encrypted value is sent to the server and used to update the key share along with a new auth_pubkey for the updated key. The previous key share is then deleted securely. +The server does not ever receive any other information regarding the client state. + +Token ID Generation: + +Valid Token IDs (token_id) can be generated by first initialising a token_id (GET api.mercurylayer.com/token/token_gen) and then agreeing to the terms of use (GET api.mercurylayer.com/token/token_init/). +This returns a JSON object that specifies an amount (in EUR) required to be paid in BTC via a Lightning invoice or on-chain. The JSON object contains the invoice and swiss-bitcoin-pay.ch invoice ID (the invoice can be viewed at api.swiss-bitcoin-pay.ch/checkout/). +Once the invoice has been paid (via the Lightning Network or on-chain) the token_id is verified (GET api.mercurylayer.com/token/token_verify/). +The token_id is now valid and can be used to generate a blind key share 'session' (see docs.mercurylayer.com for API details). + +The 'session' will maintain the key share privately for a period of 12 months, or until the session is closed by the user. +The session will enable the generation of up to 10,000 blind partial signatures and up to 10,000 key update operations. + +Security and User responsibility: + +All services provided by Mercury Layer are on a non-custodial basis. The Mercury service software does not have access to, or the ability to decrypt or access a user’s wallet. +Mercury Layer service does not keep or store User’s keys. The safekeeping of User’s keys is the sole responsibility of the User. +Mercury Layer service will not ask for recovery words, passwords or similar security-related information. Users should never provide any security-critical information to any person purporting to represent Commerceblock, its affiliates or partners. +The user bears the sole responsibility for performing the broadcast of backup transactions. Commerceblock will not be held responsible for failures to perform this function on time. +Users use this service in their own discretion and in compliance with all applicable laws and regulations. Users assume full responsibility for the consequences of their use of the service, including the safekeeping of their recovery words, passwords and stored keys, and user uses the services at their own risk. +Mercury Layer service is unable to monitor or regulate the User’s use of the services, due to the nature of the blinded cryptography employed. + +User warranties: +The User confirms and warrants that: + +- Where they are representing a legal entity or company, that they have the authorisation and power to bind the legal entity or company to the terms of service agreement and/or to use this service on behalf of that entity or company. +- That they have legal capacity to accept these terms and conditions and enter into this agreement. The service is not available to persons under the age of 18 years old. Users who do not qualify are not permitted to use the Mercury Layer service unless specifically permitted to contract under their applicable domestic law. +- They are using the services in compliance with their own local laws and jurisdiction. +- The user is aware that national taxation laws may apply to Bitcoin transactions. The User undertakes sole responsibility for determining, calculating and paying any taxes or duties applicable to their transactions under the laws or regulations applicable to their use of the service. Commerceblock Limited will not calculate, determine, pay, collect any revenue on behalf of any national government or user. +- Users assume use of the service at their own risk. Commerceblock is not liable for the actions, decisions or other behaviour of the user taken in reliance on information provided by third party services. + +Prohibited Activities: + +Notwithstanding the generality of the foregoing, the User agrees to use Mercury Layer service in a lawful manner and to refrain from any activity which hinders or otherwise adversely affects the performance of or the provision by Commerceblock of its services to the User or any other users. +The User undertakes not to "Reverse Engineer", change, modify, hack, translate, copy, distribute, pledge, assign, transfer, make derivative works, exploit, encumber or crack any portion of the service. +The User specifically agrees to defend, indemnify and hold harmless Commerceblock against any and all claims, costs, losses, damages, liability, judgments and expenses (including without limitation costs and reasonable attorneys’ fees) in connection with or arising from or in any way related to the use of the Mercury Layer service by the User in breach of these Terms of Use or use of the Mercury Layer service. +The User undertakes to inform Commerceblock immediately, or as early as possible, of any use of the Mercury Software by it, whether advertent or inadvertent which may negatively affect the rights of or cause any loss or damage to, any other person or entity. + +Fees for services: + +The fee charged for the use of the Mercury Layer service is taken in advance via swiss-bitcoin-pay.ch. +The User will be liable for transactions fees charged by the Bitcoin network, a third party separate of Commerceblock. + +Inapplicability of financial regulation law: + +Commerceblock limited is not a financial institution and does not provide banking services to the User. +Commerceblock limited does not perform any acts as a bank, including but not limited to receiving money deposits, extending credit facilities, investment of own or User funds, buying and selling money market instruments, providing money transmission services, buying and selling foreign currency, issuing and administering means of payment, money brokering, safekeeping and administration of valuables, providing portfolio management or advice or in any other way acting as a custodian, possessor or guardian, exchange or financial intermediary of or for the User’s Bitcoins. +The Mercury Layer Service does not have control or custody over the funds and does not possess, store or transmit value belonging to others. +The User accepts full knowledge that Commerceblock Limited is not performing the functions of a financial institution or bank and that the transactions undertaken using the Mercury Layer service are exempt from the provisions of law applying to financial institutions. + +Assumption of liability: + +The User assumes the full risk and conditions of liability attaching to the use of the Mercury Layer service. +TO THE MAXIMUM EXTENT PERMITTED BY LAW, UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, DELICT/TORT, CONTRACT OR OTHERWISE, SHALL COMMERCEBLOCK LIMITED, OR ANY OF ITS UNDERLYING SERVICE PROVIDERS, BUSINESS PARTNERS, INFORMATION PROVIDERS, ACCOUNT PROVIDERS, LICENSORS, OFFICERS, DIRECTORS, EMPLOYEES, DISTRIBUTORS OR AGENTS; BE LIABLE TO THE USER OR ANY OTHER PERSON FOR ANY MONEY DAMAGES, WHETHER DIRECT, INDIRECT, SPECIAL, INCIDENTAL, COVER, RELIANCE OR CONSEQUENTIAL DAMAGES, EVEN IF COMMERCEBLOCK LIMITED SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. +IN THE EVENT THAT, NOTWITHSTANDING THE FOREGOING, COMMERCEBLOCK LIMITED IS FOUND LIABLE TO THE USER FOR DAMAGES FROM ANY CAUSE WHATSOEVER, AND REGARDLESS OF THE FORM OF THE ACTION [WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), DELICT, SOFTWARE LIABILITY OR OTHERWISE], THE MAXIMUM AGGREGATE LIABILITY OF COMMERCEBLOCK LIMITED TO THE USER ARISING IN CONNECTION WITH THIS AGREEMENT SHALL BE LIMITED TO THE AMOUNT THE USER PAID FOR THE SERVICE IN THE TWELVE (12) MONTHS PRIOR TO THE ACCRUAL OF THE APPLICABLE CLAIM, LESS ANY DAMAGES PREVIOUSLY PAID BY COMMERCEBLOCK LIMITED TO THE USER IN THAT TWELVE (12) MONTH PERIOD. + +These Terms of Use constitute the entire agreement (complete and exclusive) between Commerceblock Limited and the User and supersede or replace any previous or contemporaneous terms or agreements, representations, warranties or understandings, whether written or oral. +If any provision of the Agreement is found to be unenforceable or invalid, that provision will be limited or eliminated to the minimum extent necessary so that this Agreement will otherwise remain in full force, in effect and enforceable. + +Assignment: + +The rights and obligations arising under these Terms and Conditions may be assigned to and become binding on the parties’ parent companies, subsidiaries, or legal affiliates and will survive a merger, consolidation, or sale of Commerceblock Limited’s assets. + +No waiver: + +Delayed, late or failed performance by Commerceblock Limited to exercise or enforce any right or remedy (or any part thereof) accruing to it under these Terms of Use or by law does not constated a waiver of that or any other right or remedy. Commerceblock Limited will not be precluded from further exercising that or any other lawful right or remedy. + +Governing law and choice of jurisdiction: + +Any dispute or claim arising out of or in connection with the use of Commerceblock Limited’s services, including disputes related to or arising from these Terms of Use, shall be governed exclusively by UK law and the courts of UK shall have exclusive jurisdiction to hear and determine any such disputes or claims. +Commerceblock Limited will not be held liable for actions of its users in breach of foreign laws. End users are solely responsible for ensuring that they comply with the laws of the country in which they are resident, domiciled or otherwise present. From 927b56437c1f21353cccc09424c5633718ea61d0 Mon Sep 17 00:00:00 2001 From: DhananjayPurohit Date: Fri, 6 Sep 2024 16:10:23 +0530 Subject: [PATCH 6/7] chore: remove nodejs tests --- .github/workflows/tests.yml | 8 +- .../nodejs/test/ta02-duplicate-deposits.mjs | 166 --- .../test/tb04-simple-lightning-latch.mjs | 594 --------- clients/apps/nodejs/test/test-utils.mjs | 50 - clients/apps/nodejs/test_atomic_swap.js | 856 ------------- clients/apps/nodejs/test_basic_workflow.js | 232 ---- clients/apps/nodejs/test_basic_workflow2.js | 1072 ----------------- 7 files changed, 1 insertion(+), 2977 deletions(-) delete mode 100644 clients/apps/nodejs/test/ta02-duplicate-deposits.mjs delete mode 100644 clients/apps/nodejs/test/tb04-simple-lightning-latch.mjs delete mode 100644 clients/apps/nodejs/test/test-utils.mjs delete mode 100644 clients/apps/nodejs/test_atomic_swap.js delete mode 100644 clients/apps/nodejs/test_basic_workflow.js delete mode 100644 clients/apps/nodejs/test_basic_workflow2.js diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index c94282d9..6367fc53 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -168,13 +168,7 @@ jobs: run: | cd clients/tests/web sudo chmod -R 755 ./data_bitcoin_regtest - npx vitest --browser.name=chromium --browser.headless - - name: Run Client-Side Tests - run: | - cd clients/apps/nodejs - node test_basic_workflow2.js - node test_atomic_swap.js - mocha ./test/tb04-simple-lightning-latch.mjs --exit + npx vitest --browser.name=chromium --browser.headless - name: Tear Down run: | docker-compose -f docker-compose-test.yml down diff --git a/clients/apps/nodejs/test/ta02-duplicate-deposits.mjs b/clients/apps/nodejs/test/ta02-duplicate-deposits.mjs deleted file mode 100644 index 92d73111..00000000 --- a/clients/apps/nodejs/test/ta02-duplicate-deposits.mjs +++ /dev/null @@ -1,166 +0,0 @@ -import { expect } from 'chai'; -import client_config from '../client_config.js'; -import mercurynodejslib from 'mercurynodejslib'; -import { CoinStatus } from 'mercurynodejslib/coin_enum.js'; -import { createWallet, removeDatabase, getnewaddress, generateBlock, depositCoin } from './test-utils.mjs'; - -describe('TA02 - Duplicated Deposits', function() { - - context('Withdraw Flow', () => { - it('should complete successfully', async () => { - - const clientConfig = client_config.load(); - await removeDatabase(clientConfig); - - let wallet_1_name = "w1"; - let wallet_2_name = "w2"; - let wallet1 = await createWallet(clientConfig, wallet_1_name); - let wallet2 = await createWallet(clientConfig, wallet_2_name); - - const token = await mercurynodejslib.newToken(clientConfig, wallet1.name); - const tokenId = token.token_id; - - const amount1 = 10000; - const depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet1.name, amount1); - - await depositCoin(depositInfo.deposit_address, amount1); - - let amount2 = 20000; - await depositCoin(depositInfo.deposit_address, amount2); - - const coreWalletAddress = await getnewaddress(); - - await generateBlock(clientConfig.confirmationTarget, coreWalletAddress); - - const listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet1.name); - - expect(listCoins.length).to.equal(2); - - const newCoin = listCoins.find(coin => - coin.aggregated_address == depositInfo.deposit_address && - coin.status == CoinStatus.CONFIRMED - ); - - const duplicatedCoin = listCoins.find(coin => - coin.aggregated_address == depositInfo.deposit_address && - coin.status == CoinStatus.DUPLICATED - ); - - expect(newCoin).to.not.be.null; - expect(duplicatedCoin).to.not.be.null; - - expect(newCoin.duplicate_index).to.equal(0); - expect(duplicatedCoin.duplicate_index).to.equal(1); - - const transferAddress = await mercurynodejslib.newTransferAddress(clientConfig, wallet2.name, null); - - try { - await mercurynodejslib.transferSend(clientConfig, wallet1.name, newCoin.statechain_id, transferAddress.transfer_receive, false, null); - } catch (error) { - expect(error.message).to.include("Coin is duplicated. If you want to proceed, use the command '--force, -f' option. " + - "You will no longer be able to move other duplicate coins with the same statechain_id and this will cause PERMANENT LOSS of these duplicate coin funds."); - } - - const withdrawAddress = "bcrt1qn5948np2j8t68xgpceneg3ua4wcwhwrsqj8scv"; - - let txid = await mercurynodejslib.withdrawCoin(clientConfig, wallet1.name, duplicatedCoin.statechain_id, withdrawAddress, null, 1); - - expect(txid).to.be.string; - - try { - await mercurynodejslib.transferSend(clientConfig, wallet1.name, newCoin.statechain_id, transferAddress.transfer_receive, false, null); - } catch (error) { - expect(error.message).to.include("There have been withdrawals of other coins with this same statechain_id (possibly duplicates). " + - "This transfer cannot be performed because the recipient would reject it due to the difference in signature count. This coin can be withdrawn, however."); - } - - txid = await mercurynodejslib.withdrawCoin(clientConfig, wallet1.name, duplicatedCoin.statechain_id, withdrawAddress, null, 0); - - expect(txid).to.be.string; - }) - }), - - context('Transfer Flow', () => { - it('should complete successfully', async () => { - - const clientConfig = client_config.load(); - await removeDatabase(clientConfig); - - let wallet_1_name = "w1"; - let wallet_2_name = "w2"; - let wallet1 = await createWallet(clientConfig, wallet_1_name); - let wallet2 = await createWallet(clientConfig, wallet_2_name); - - const token = await mercurynodejslib.newToken(clientConfig, wallet1.name); - const tokenId = token.token_id; - - const amount1 = 10000; - const depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet1.name, amount1); - - await depositCoin(depositInfo.deposit_address, amount1); - - let amount2 = 20000; - await depositCoin(depositInfo.deposit_address, amount2); - - const coreWalletAddress = await getnewaddress(); - - await generateBlock(clientConfig.confirmationTarget, coreWalletAddress); - - let listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet1.name); - - expect(listCoins.length).to.equal(2); - - const newCoin = listCoins.find(coin => - coin.aggregated_address == depositInfo.deposit_address && - coin.status == CoinStatus.CONFIRMED - ); - - let duplicatedCoin = listCoins.find(coin => - coin.aggregated_address == depositInfo.deposit_address && - coin.status == CoinStatus.DUPLICATED - ); - - expect(newCoin).to.not.be.null; - expect(duplicatedCoin).to.not.be.null; - - expect(newCoin.duplicate_index).to.equal(0); - expect(duplicatedCoin.duplicate_index).to.equal(1); - - const transferAddress = await mercurynodejslib.newTransferAddress(clientConfig, wallet2.name, null); - - let result = await mercurynodejslib.transferSend(clientConfig, wallet1.name, newCoin.statechain_id, transferAddress.transfer_receive, true, null); - expect(result).to.have.property('statechain_id'); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet2.name); - - expect(transferReceiveResult.receivedStatechainIds).contains(newCoin.statechain_id); - expect(transferReceiveResult.receivedStatechainIds.length).to.equal(1); - - listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet1.name); - - const transferredCoin = listCoins.find(coin => - coin.aggregated_address === depositInfo.deposit_address && - coin.status === CoinStatus.TRANSFERRED - ); - - duplicatedCoin = listCoins.find(coin => - coin.aggregated_address === depositInfo.deposit_address && - coin.status === CoinStatus.DUPLICATED - ); - - expect(transferredCoin).to.not.be.null; - expect(transferredCoin.duplicate_index).to.equal(0); - - expect(duplicatedCoin).to.not.be.null; - expect(duplicatedCoin.duplicate_index).to.equal(1); - - try { - const withdrawAddress = "bcrt1qn5948np2j8t68xgpceneg3ua4wcwhwrsqj8scv"; - await mercurynodejslib.withdrawCoin(clientConfig, wallet1.name, duplicatedCoin.statechain_id, withdrawAddress, null, 1); - } catch (error) { - expect(error.response.status).to.equal(401); - expect(error.response.data.message).to.equal("Signature does not match authentication key."); - } - }) - }) -}) diff --git a/clients/apps/nodejs/test/tb04-simple-lightning-latch.mjs b/clients/apps/nodejs/test/tb04-simple-lightning-latch.mjs deleted file mode 100644 index 0ed4e187..00000000 --- a/clients/apps/nodejs/test/tb04-simple-lightning-latch.mjs +++ /dev/null @@ -1,594 +0,0 @@ -import { expect } from 'chai'; -import client_config from '../client_config.js'; -import mercurynodejslib from 'mercurynodejslib'; -import { CoinStatus } from 'mercurynodejslib/coin_enum.js'; -import crypto from 'crypto'; -import { sleep, createWallet, depositCoin, generateInvoice, payHoldInvoice, payInvoice, settleInvoice } from '../test_utils.js'; - -describe('TB04 - Lightning Latch', function() { - this.timeout(30000); - - context('Simple Transfer', () => { - it('should complete successfully', async () => { - - // await removeDatabase(); - const clientConfig = client_config.load(); - let wallet_1_name = "w_ln_1"; - let wallet_2_name = "w_ln_2"; - await createWallet(clientConfig, wallet_1_name); - await createWallet(clientConfig, wallet_2_name); - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - const tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - const usedToken = tokenList.find(token => token.token_id === tokenId); - - expect(usedToken.spent).is.true; - - await depositCoin(clientConfig, wallet_1_name, amount, depositInfo); - - const listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - expect(listCoins.length).to.equal(1); - - const coin = listCoins[0]; - - expect(coin.status).to.equal(CoinStatus.CONFIRMED); - - const paymentHash = await mercurynodejslib.paymentHash(clientConfig, wallet_1_name, coin.statechain_id); - - const transferAddress = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transferAddress.transfer_receive, false, paymentHash.batchId); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.true; - expect(transferReceiveResult.receivedStatechainIds).empty; - - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_1_name, coin.statechain_id); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.false; - expect(transferReceiveResult.receivedStatechainIds).not.empty; - - const { preimage } = await mercurynodejslib.retrievePreImage(clientConfig, wallet_1_name, coin.statechain_id, paymentHash.batchId); - - const hash = crypto.createHash('sha256') - .update(Buffer.from(preimage, 'hex')) - .digest('hex') - - expect(hash).to.equal(paymentHash.hash); - }) - }) - - context('The sender tries to get the pre-image before the batch is unlocked should fail', () => { - it('should complete successfully', async () => { - - const clientConfig = client_config.load(); - let wallet_1_name = "w_ln_3"; - let wallet_2_name = "w_ln_4"; - await createWallet(clientConfig, wallet_1_name); - await createWallet(clientConfig, wallet_2_name); - - const amount = 10000; - let token = undefined; - let tokenId = undefined; - let depositInfo = undefined; - let tokenList = undefined; - let usedToken = undefined; - let listCoins = undefined; - - token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - tokenId = token.token_id; - - depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - usedToken = tokenList.find(token => token.token_id === tokenId); - - expect(usedToken.spent).is.true; - - await depositCoin(clientConfig, wallet_1_name, amount, depositInfo); - - listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - expect(listCoins.length).to.equal(1); - - const coin1 = listCoins[0]; - - expect(coin1.status).to.equal(CoinStatus.CONFIRMED); - - const paymentHash1 = await mercurynodejslib.paymentHash(clientConfig, wallet_1_name, coin1.statechain_id); - - token = await mercurynodejslib.newToken(clientConfig, wallet_2_name); - tokenId = token.token_id; - - depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_2_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_2_name); - usedToken = tokenList.find(token => token.token_id === tokenId); - - expect(usedToken.spent).is.true; - - await depositCoin(clientConfig, wallet_2_name, amount, depositInfo); - - listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet_2_name); - - expect(listCoins.length).to.equal(1); - - const coin2 = listCoins[0]; - - expect(coin2.status).to.equal(CoinStatus.CONFIRMED); - - const paymentHash2 = await mercurynodejslib.paymentHash(clientConfig, wallet_2_name, coin2.statechain_id); - - const transferAddress1 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_1_name, null); - const transferAddress2 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transferAddress1.transfer_receive, false, paymentHash1.batchId); - await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transferAddress2.transfer_receive, false, paymentHash2.batchId); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_1_name); - - expect(transferReceiveResult.isThereBatchLocked).is.true; - expect(transferReceiveResult.receivedStatechainIds).empty; - - try { - const { preimage } = await mercurynodejslib.retrievePreImage(clientConfig, wallet_1_name, coin1.statechain_id, paymentHash1.batchId); - } catch (error) { - // Assert the captured error message - const expectedMessage = 'Request failed with status code 404'; - expect(error.message).to.equal(expectedMessage); - } - - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_1_name, coin1.statechain_id); - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_2_name, coin2.statechain_id); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.false; - expect(transferReceiveResult.receivedStatechainIds).not.empty; - - const { preimage } = await mercurynodejslib.retrievePreImage(clientConfig, wallet_1_name, coin1.statechain_id, paymentHash1.batchId); - - const hash = crypto.createHash('sha256') - .update(Buffer.from(preimage, 'hex')) - .digest('hex') - - expect(hash).to.equal(paymentHash1.hash); - }) - }) - - context('Statecoin sender can recover (resend their coin) after batch timeout without completion', () => { - it('should complete successfully', async () => { - - const clientConfig = client_config.load(); - let wallet_1_name = "w_ln_5"; - let wallet_2_name = "w_ln_6"; - await createWallet(clientConfig, wallet_1_name); - await createWallet(clientConfig, wallet_2_name); - - const amount = 10000; - let token = undefined; - let tokenId = undefined; - let depositInfo = undefined; - let tokenList = undefined; - let usedToken = undefined; - let listCoins = undefined; - - token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - tokenId = token.token_id; - - depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - usedToken = tokenList.find(token => token.token_id === tokenId); - - expect(usedToken.spent).is.true; - - await depositCoin(clientConfig, wallet_1_name, amount, depositInfo); - - listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - expect(listCoins.length).to.equal(1); - - const coin1 = listCoins[0]; - - expect(coin1.status).to.equal(CoinStatus.CONFIRMED); - - const paymentHash1 = await mercurynodejslib.paymentHash(clientConfig, wallet_1_name, coin1.statechain_id); - - token = await mercurynodejslib.newToken(clientConfig, wallet_2_name); - tokenId = token.token_id; - - depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_2_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_2_name); - usedToken = tokenList.find(token => token.token_id === tokenId); - - expect(usedToken.spent).is.true; - - await depositCoin(clientConfig, wallet_2_name, amount, depositInfo); - - listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet_2_name); - - expect(listCoins.length).to.equal(1); - - const coin2 = listCoins[0]; - - expect(coin2.status).to.equal(CoinStatus.CONFIRMED); - - const paymentHash2 = await mercurynodejslib.paymentHash(clientConfig, wallet_2_name, coin2.statechain_id); - - const transferAddress1 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_1_name, null); - const transferAddress2 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transferAddress1.transfer_receive, false, paymentHash1.batchId); - await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transferAddress2.transfer_receive, false, paymentHash1.batchId); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_1_name); - - expect(transferReceiveResult.isThereBatchLocked).is.true; - expect(transferReceiveResult.receivedStatechainIds).empty; - - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_1_name, coin1.statechain_id); - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_2_name, coin2.statechain_id); - - await sleep(20000); - - let errorMessage; - console.error = (msg) => { - errorMessage = msg; - }; - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - // Assert the captured error message - const expectedMessage = 'Failed to update transfer message'; - expect(errorMessage).contains(expectedMessage); - - const transferAddress3 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_1_name, null); - const transferAddress4 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transferAddress3.transfer_receive, false, paymentHash2.batchId); - await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transferAddress4.transfer_receive, false, paymentHash2.batchId); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_1_name); - - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_1_name, coin1.statechain_id); - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_2_name, coin2.statechain_id); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.false; - expect(transferReceiveResult.receivedStatechainIds).not.empty; - - const { preimage } = await mercurynodejslib.retrievePreImage(clientConfig, wallet_1_name, coin1.statechain_id, paymentHash1.batchId); - - const hash = crypto.createHash('sha256') - .update(Buffer.from(preimage, 'hex')) - .digest('hex') - - expect(hash).to.equal(paymentHash1.hash); - }) - }) - - context('Statecoin trade with invoice creation, payment and settlement', () => { - it('should complete successfully', async () => { - - // await removeDatabase(); - const clientConfig = client_config.load(); - let wallet_1_name = "w_ln_7"; - let wallet_2_name = "w_ln_8"; - await createWallet(clientConfig, wallet_1_name); - await createWallet(clientConfig, wallet_2_name); - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - const tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - const usedToken = tokenList.find(token => token.token_id === tokenId); - - expect(usedToken.spent).is.true; - - await depositCoin(clientConfig, wallet_1_name, amount, depositInfo); - - const listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - expect(listCoins.length).to.equal(1); - - const coin = listCoins[0]; - - expect(coin.status).to.equal(CoinStatus.CONFIRMED); - - const paymentHash = await mercurynodejslib.paymentHash(clientConfig, wallet_1_name, coin.statechain_id); - - const invoice = await generateInvoice(paymentHash.hash, amount); - - payInvoice(invoice.payment_request); - - const transferAddress = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transferAddress.transfer_receive, false, paymentHash.batchId); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.true; - expect(transferReceiveResult.receivedStatechainIds).empty; - - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_1_name, coin.statechain_id); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.false; - expect(transferReceiveResult.receivedStatechainIds).not.empty; - - const { preimage } = await mercurynodejslib.retrievePreImage(clientConfig, wallet_1_name, coin.statechain_id, paymentHash.batchId); - - const hash = crypto.createHash('sha256') - .update(Buffer.from(preimage, 'hex')) - .digest('hex') - - expect(hash).to.equal(paymentHash.hash); - - await settleInvoice(preimage); - }) - }) - - context('Receiver tries to transfer invoice amount to another invoice before preimage retrieval should fail', () => { - it('should complete successfully', async () => { - - // await removeDatabase(); - const clientConfig = client_config.load(); - let wallet_1_name = "w_ln_9"; - let wallet_2_name = "w_ln_10"; - await createWallet(clientConfig, wallet_1_name); - await createWallet(clientConfig, wallet_2_name); - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 60000; - const depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - const tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - const usedToken = tokenList.find(token => token.token_id === tokenId); - - expect(usedToken.spent).is.true; - - await depositCoin(clientConfig, wallet_1_name, amount, depositInfo); - - const listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - expect(listCoins.length).to.equal(1); - - const coin = listCoins[0]; - - expect(coin.status).to.equal(CoinStatus.CONFIRMED); - - const paymentHash = await mercurynodejslib.paymentHash(clientConfig, wallet_1_name, coin.statechain_id); - - const invoice = await generateInvoice(paymentHash.hash, amount); - - payHoldInvoice(invoice.payment_request); - - const transferAddress = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transferAddress.transfer_receive, false, paymentHash.batchId); - - const hashFromServer = await mercurynodejslib.getPaymentHash(clientConfig, paymentHash.batchId); - - expect(hashFromServer).to.equal(paymentHash.hash); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.true; - expect(transferReceiveResult.receivedStatechainIds).empty; - - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_1_name, coin.statechain_id); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.false; - expect(transferReceiveResult.receivedStatechainIds).not.empty; - - const { preimage } = await mercurynodejslib.retrievePreImage(clientConfig, wallet_1_name, coin.statechain_id, paymentHash.batchId); - - const hash = crypto.createHash('sha256') - .update(Buffer.from(preimage, 'hex')) - .digest('hex') - - expect(hash).to.equal(paymentHash.hash); - - const paymentHashSecond = "b1f55a2f2eabb08ed9d6e15a053a6ac84d04d1c017de5a42caaec98b8d2ff738" - const invoiceSecond = await generateInvoice(paymentHashSecond, amount); - - try { - await payInvoice(invoiceSecond.payment_request); - } catch (error) { - console.error('Error:', error); - expect(error.message).to.include('failed'); - } - }) - }) - - context('Statecoin sender sends coin without batch_id (receiver should still be able to receive, but no pre-image revealed)', () => { - it('should complete successfully', async () => { - - // await removeDatabase(); - const clientConfig = client_config.load(); - let wallet_1_name = "w_ln_11"; - let wallet_2_name = "w_ln_12"; - await createWallet(clientConfig, wallet_1_name); - await createWallet(clientConfig, wallet_2_name); - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - const tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - const usedToken = tokenList.find(token => token.token_id === tokenId); - - expect(usedToken.spent).is.true; - - await depositCoin(clientConfig, wallet_1_name, amount, depositInfo); - - const listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - expect(listCoins.length).to.equal(1); - - const coin = listCoins[0]; - - expect(coin.status).to.equal(CoinStatus.CONFIRMED); - - const paymentHash = await mercurynodejslib.paymentHash(clientConfig, wallet_1_name, coin.statechain_id); - - const transferAddress = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transferAddress.transfer_receive, false, null); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.false; - expect(transferReceiveResult.receivedStatechainIds).not.empty; - - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_1_name, coin.statechain_id); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.false; - expect(transferReceiveResult.receivedStatechainIds).is.empty; - - let hash; - try { - const { preimage } = await mercurynodejslib.retrievePreImage(clientConfig, wallet_1_name, coin.statechain_id, paymentHash.batchId); - hash = crypto.createHash('sha256') - .update(Buffer.from(preimage, 'hex')) - .digest('hex') - expect(hash).to.equal(paymentHash.hash); - } catch (error) { - console.error('Error:', error); - expect(error.message).to.include('failed'); - } - }) - }) - - context('Sender sends coin without batch_id, and then resends to a different address (to attempt to steal), and then attempts to retrieve the pre-image, should fail (and LN payment cannot be claimed)', () => { - it('should complete successfully', async () => { - - // await removeDatabase(); - const clientConfig = client_config.load(); - let wallet_1_name = "w_ln_13"; - let wallet_2_name = "w_ln_14"; - let wallet_3_name = "w_ln_15"; - await createWallet(clientConfig, wallet_1_name); - await createWallet(clientConfig, wallet_2_name); - await createWallet(clientConfig, wallet_3_name); - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - const tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - const usedToken = tokenList.find(token => token.token_id === tokenId); - - expect(usedToken.spent).is.true; - - await depositCoin(clientConfig, wallet_1_name, amount, depositInfo); - - const listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - expect(listCoins.length).to.equal(1); - - const coin = listCoins[0]; - - expect(coin.status).to.equal(CoinStatus.CONFIRMED); - - const paymentHash = await mercurynodejslib.paymentHash(clientConfig, wallet_1_name, coin.statechain_id); - - const transferAddress = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transferAddress.transfer_receive, false, null); - - const transferAddressSecond = await mercurynodejslib.newTransferAddress(clientConfig, wallet_3_name, null); - - await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transferAddressSecond.transfer_receive, false, null); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - - expect(transferReceiveResult.isThereBatchLocked).is.false; - expect(transferReceiveResult.receivedStatechainIds).not.empty; - - await mercurynodejslib.confirmPendingInvoice(clientConfig, wallet_1_name, coin.statechain_id); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - - expect(transferReceiveResult.isThereBatchLocked).is.false; - expect(transferReceiveResult.receivedStatechainIds).is.empty; - - let hash; - try { - const { preimage } = await mercurynodejslib.retrievePreImage(clientConfig, wallet_1_name, coin.statechain_id, paymentHash.batchId); - hash = crypto.createHash('sha256') - .update(Buffer.from(preimage, 'hex')) - .digest('hex') - expect(hash).to.equal(paymentHash.hash); - } catch (error) { - console.error('Error:', error); - expect(error.message).to.include('failed'); - } - }) - }) - - context('Coin receiver creates a non hold invoice, and sends to sender (i.e. an invoice with the a different payment hash). Sender should be able to determine this.', () => { - it('should complete successfully', async () => { - - // await removeDatabase(); - const clientConfig = client_config.load(); - let wallet_1_name = "w_ln_16"; - await createWallet(clientConfig, wallet_1_name); - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const depositInfo = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - const tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - const usedToken = tokenList.find(token => token.token_id === tokenId); - - expect(usedToken.spent).is.true; - - await depositCoin(clientConfig, wallet_1_name, amount, depositInfo); - - const listCoins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - expect(listCoins.length).to.equal(1); - - const coin = listCoins[0]; - - expect(coin.status).to.equal(CoinStatus.CONFIRMED); - - const paymentHash = await mercurynodejslib.paymentHash(clientConfig, wallet_1_name, coin.statechain_id); - - const paymentHashSecond = "a3b5f72d4e8cb07cd9a6e17c054a7ac84d05e1c018fe5b43cbbef98a9d3ff839" - const invoiceSecond = await generateInvoice(paymentHashSecond, amount); - - const isInvoiceValid = await mercurynodejslib.verifyInvoice(clientConfig, paymentHash.batchId, invoiceSecond.payment_request); - expect(isInvoiceValid).is.false; - }) - }) -}) diff --git a/clients/apps/nodejs/test/test-utils.mjs b/clients/apps/nodejs/test/test-utils.mjs deleted file mode 100644 index 1365bc11..00000000 --- a/clients/apps/nodejs/test/test-utils.mjs +++ /dev/null @@ -1,50 +0,0 @@ -import { promisify } from 'node:util'; -import { exec as execCallback } from 'node:child_process'; -import mercurynodejslib from 'mercurynodejslib'; -import { promises as fs } from 'fs'; - -const exec = promisify(execCallback); - -async function createWallet(clientConfig, walletName) { - - let wallet = await mercurynodejslib.createWallet(clientConfig, walletName); - return wallet; - - // TODO: add more assertions - } - - -async function removeDatabase(clientConfig) { - try { - await fs.unlink(clientConfig.databaseFile); - } catch (error) { - if (error.code !== 'ENOENT') { - console.error('Error occurred:', error); - } - // ENOENT means "No such file or directory", so we ignore this error - } -} - -async function getnewaddress() { - const generateBlockCommand = `docker exec $(docker ps -qf "name=lnd_docker-bitcoind-1") bitcoin-cli -regtest -rpcuser=user -rpcpassword=pass getnewaddress`; - const { stdout, stderr } = await exec(generateBlockCommand); - if (stderr) { - console.error('Error:', stderr); - return null; - } - return stdout.trim(); -} - -async function generateBlock(numBlocks, address) { - const generateBlockCommand = `docker exec $(docker ps -qf "name=lnd_docker-bitcoind-1") bitcoin-cli -regtest -rpcuser=user -rpcpassword=pass generatetoaddress ${numBlocks} ${address}`; - await exec(generateBlockCommand); -} - -async function depositCoin(deposit_address, amountInSats) { - const amountInBtc = amountInSats / 100000000; - - const sendBitcoinCommand = `docker exec $(docker ps -qf "name=lnd_docker-bitcoind-1") bitcoin-cli -regtest -rpcuser=user -rpcpassword=pass sendtoaddress ${deposit_address} ${amountInBtc}`; - await exec(sendBitcoinCommand); -} - -export { createWallet, removeDatabase, getnewaddress, generateBlock, depositCoin }; \ No newline at end of file diff --git a/clients/apps/nodejs/test_atomic_swap.js b/clients/apps/nodejs/test_atomic_swap.js deleted file mode 100644 index 6156a89f..00000000 --- a/clients/apps/nodejs/test_atomic_swap.js +++ /dev/null @@ -1,856 +0,0 @@ -const assert = require('node:assert/strict'); -const mercurynodejslib = require('mercurynodejslib'); -const { CoinStatus } = require('mercurynodejslib/coin_enum'); -const { sleep, createWallet, generateBlock, depositCoin } = require('./test_utils'); -const client_config = require('./client_config'); - -async function atomicSwapSuccess(clientConfig, wallet_1_name, wallet_2_name, wallet_3_name, wallet_4_name) { - - const amount = 10000; - let token = undefined; - let tokenId = undefined; - let deposit_info = undefined; - let tokenList = undefined; - let usedToken = undefined; - - token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin1 = undefined; - - console.log("coin: ", coin1); - - while (!coin1) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin1 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin1); - - token = await mercurynodejslib.newToken(clientConfig, wallet_2_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_2_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_2_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_2_name, amount, deposit_info); - - let coin2 = undefined; - - console.log("coin: ", coin2); - - while (!coin2) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_2_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin2 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin2); - - const generateBatchId = true; - - let transfer_address_w3 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_3_name, generateBatchId); - let transfer_address_w4 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_4_name, null); - - let coin3 = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transfer_address_w3.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin3); - - let coin4 = await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transfer_address_w4.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin4); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - console.log("transferReceiveResult: ", transferReceiveResult); - assert(transferReceiveResult.isThereBatchLocked === true); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_4_name); - let received_statechain_ids_w4 = transferReceiveResult.receivedStatechainIds; - - console.log("received_statechain_ids: ", received_statechain_ids_w4); - - assert(received_statechain_ids_w4.length > 0); - assert(received_statechain_ids_w4[0] == coin4.statechain_id); - - // transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - // received_statechain_ids_w3 = transferReceiveResult.receivedStatechainIds; - - // console.log("received_statechain_ids: ", received_statechain_ids_w3); - - // assert(received_statechain_ids_w3.length > 0); - // assert(received_statechain_ids_w3[0] == coin3.statechain_id); -} - -async function atomicSwapWithSecondBatchIdMissing(clientConfig, wallet_1_name, wallet_2_name, wallet_3_name, wallet_4_name) { - - const amount = 10000; - let token = undefined; - let tokenId = undefined; - let deposit_info = undefined; - let tokenList = undefined; - let usedToken = undefined; - - token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin1 = undefined; - - console.log("coin: ", coin1); - - while (!coin1) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin1 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin1); - - token = await mercurynodejslib.newToken(clientConfig, wallet_2_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_2_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_2_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_2_name, amount, deposit_info); - - let coin2 = undefined; - - console.log("coin: ", coin2); - - while (!coin2) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_2_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin2 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin2); - - const generateBatchId = true; - - let transfer_address_w3 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_3_name, generateBatchId); - let transfer_address_w4 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_4_name, null); - - let coin3 = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transfer_address_w3.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin3); - - transfer_address_w3.batchId = ""; - - let coin4 = await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transfer_address_w4.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin4); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - let received_statechain_ids_w3 = transferReceiveResult.receivedStatechainIds; - - console.log("received_statechain_ids: ", received_statechain_ids_w3); - - assert(received_statechain_ids_w3.length > 0); - assert(received_statechain_ids_w3[0] == coin3.statechain_id); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_4_name); - let received_statechain_ids_w4 = transferReceiveResult.receivedStatechainIds; - - console.log("received_statechain_ids: ", received_statechain_ids_w4); - - assert(received_statechain_ids_w4.length > 0); - assert(received_statechain_ids_w4[0] == coin4.statechain_id); -} - -async function atomicSwapWithoutFirstBatchId(clientConfig, wallet_1_name, wallet_2_name, wallet_3_name, wallet_4_name) { - - const amount = 10000; - let token = undefined; - let tokenId = undefined; - let deposit_info = undefined; - let tokenList = undefined; - let usedToken = undefined; - - token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin1 = undefined; - - console.log("coin: ", coin1); - - while (!coin1) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin1 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin1); - - token = await mercurynodejslib.newToken(clientConfig, wallet_2_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_2_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_2_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_2_name, amount, deposit_info); - - let coin2 = undefined; - - console.log("coin: ", coin2); - - while (!coin2) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_2_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin2 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin2); - - const generateBatchId = true; - - let transfer_address_w3 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_3_name, generateBatchId); - let transfer_address_w4 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_4_name, null); - - let coin3 = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transfer_address_w3.transfer_receive, false, null); - console.log("coin transferSend: ", coin3); - - let coin4 = await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transfer_address_w4.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin4); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - let received_statechain_ids_w3 = transferReceiveResult.receivedStatechainIds; - - console.log("received_statechain_ids: ", received_statechain_ids_w3); - - assert(received_statechain_ids_w3.length > 0); - assert(received_statechain_ids_w3[0] == coin3.statechain_id); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_4_name); - let received_statechain_ids_w4 = transferReceiveResult.receivedStatechainIds; - - console.log("received_statechain_ids: ", received_statechain_ids_w4); - - assert(received_statechain_ids_w4.length > 0); - assert(received_statechain_ids_w4[0] == coin4.statechain_id); -} - -async function atomicSwapWithTimeout(clientConfig, wallet_1_name, wallet_2_name, wallet_3_name, wallet_4_name) { - - const amount = 10000; - let token = undefined; - let tokenId = undefined; - let deposit_info = undefined; - let tokenList = undefined; - let usedToken = undefined; - - token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin1 = undefined; - - console.log("coin: ", coin1); - - while (!coin1) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin1 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin1); - - token = await mercurynodejslib.newToken(clientConfig, wallet_2_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_2_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_2_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_2_name, amount, deposit_info); - - let coin2 = undefined; - - console.log("coin: ", coin2); - - while (!coin2) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_2_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin2 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin2); - - const generateBatchId = true; - - let transfer_address_w3 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_3_name, generateBatchId); - let transfer_address_w4 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_4_name, null); - - let coin3 = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transfer_address_w3.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin3); - - let coin4 = await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transfer_address_w4.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin4); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - let received_statechain_ids_w3 = transferReceiveResult.receivedStatechainIds; - await sleep(20000); - - assert(transferReceiveResult.isThereBatchLocked === true); - - let errorMessage; - console.error = (msg) => { - errorMessage = msg; - }; - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_4_name); - let received_statechain_ids_w4 = transferReceiveResult.receivedStatechainIds; - - // Assert the captured error message - const expectedMessage = 'Failed to update transfer message'; - assert.ok(errorMessage.includes(expectedMessage)); - - transfer_address_w3 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_3_name, generateBatchId); - transfer_address_w4 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_4_name, null); - - coin3 = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transfer_address_w3.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin3); - - coin4 = await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transfer_address_w4.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin4); - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - received_statechain_ids_w3 = transferReceiveResult.receivedStatechainIds; - - transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_4_name); - received_statechain_ids_w4 = transferReceiveResult.receivedStatechainIds; - - console.log("received_statechain_ids: ", received_statechain_ids_w4); - - assert(received_statechain_ids_w4.length > 0); - assert(received_statechain_ids_w4[0] == coin4.statechain_id); - - // transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - // received_statechain_ids_w3 = transferReceiveResult.receivedStatechainIds; - - // console.log("received_statechain_ids: ", received_statechain_ids_w3); - - // assert(received_statechain_ids_w3.length > 0); - // assert(received_statechain_ids_w3[0] == coin3.statechain_id); -} - -async function atomicSwapWithFirstPartySteal(clientConfig, wallet_1_name, wallet_2_name, wallet_3_name, wallet_4_name) { - - const amount = 10000; - let token = undefined; - let tokenId = undefined; - let deposit_info = undefined; - let tokenList = undefined; - let usedToken = undefined; - - token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin1 = undefined; - - console.log("coin: ", coin1); - - while (!coin1) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin1 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin1); - - token = await mercurynodejslib.newToken(clientConfig, wallet_2_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_2_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_2_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_2_name, amount, deposit_info); - - let coin2 = undefined; - - console.log("coin: ", coin2); - - while (!coin2) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_2_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin2 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin2); - - const generateBatchId = true; - - let transfer_address_w3 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_3_name, generateBatchId); - let transfer_address_w4 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_4_name, null); - - let coin3 = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transfer_address_w3.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin3); - - let coin4 = await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transfer_address_w4.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin4); - - let transfer_address_w3_for_steal = await mercurynodejslib.newTransferAddress(clientConfig, wallet_3_name, generateBatchId); - console.log("transfer address for steal", transfer_address_w3_for_steal); - - let coin_to_steal = undefined; - try { - coin_to_steal = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transfer_address_w3_for_steal.transfer_receive, false, transfer_address_w3.batchId); - } catch (error) { - // Assert the captured error message - const expectedMessage = 'expected a string argument, found undefined'; - assert.ok(error.message.includes(expectedMessage)); - } - - console.log("coin to steal transferSend: ", coin_to_steal); - - let received_statechain_ids_w3 = undefined; - try { - received_statechain_ids_w3 = mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - } catch (error) { - // Assert the captured error message - const expectedMessage = 'num_sigs is not correct'; - assert.ok(error.message.includes(expectedMessage)); - } - await sleep(3000); - - let received_statechain_ids_w4 = undefined; - try { - received_statechain_ids_w4 = await mercurynodejslib.transferReceive(clientConfig, wallet_4_name); - } catch (error) { - // Assert the captured error message - const expectedMessage = 'num_sigs is not correct'; - assert.ok(error.message.includes(expectedMessage)); - } - - try { - received_statechain_ids_w3 = await mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - } catch (error) { - // Assert the captured error message - const expectedMessage = 'num_sigs is not correct'; - assert.ok(error.message.includes(expectedMessage)); - } -} - -async function atomicSwapWithSecondPartySteal(clientConfig, wallet_1_name, wallet_2_name, wallet_3_name, wallet_4_name) { - - const amount = 10000; - let token = undefined; - let tokenId = undefined; - let deposit_info = undefined; - let tokenList = undefined; - let usedToken = undefined; - - token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin1 = undefined; - - console.log("coin: ", coin1); - - while (!coin1) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin1 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin1); - - token = await mercurynodejslib.newToken(clientConfig, wallet_2_name); - tokenId = token.token_id; - - deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_2_name, amount); - - tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_2_name); - - usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_2_name, amount, deposit_info); - - let coin2 = undefined; - - console.log("coin: ", coin2); - - while (!coin2) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_2_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - generateBlock(1); - continue; - } - - coin2 = coinsWithStatechainId[0]; - break; - } - - console.log("coin: ", coin2); - - const generateBatchId = true; - - let transfer_address_w3 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_3_name, generateBatchId); - let transfer_address_w4 = await mercurynodejslib.newTransferAddress(clientConfig, wallet_4_name, null); - - let coin3 = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin1.statechain_id, transfer_address_w3.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin3); - - let coin4 = await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transfer_address_w4.transfer_receive, false, transfer_address_w3.batchId); - console.log("coin transferSend: ", coin4); - - let transfer_address_w4_for_steal = await mercurynodejslib.newTransferAddress(clientConfig, wallet_4_name, generateBatchId); - console.log("transfer address for steal", transfer_address_w4_for_steal); - - let coin_to_steal = undefined; - try { - coin_to_steal = await mercurynodejslib.transferSend(clientConfig, wallet_2_name, coin2.statechain_id, transfer_address_w4_for_steal.transfer_receive, false, transfer_address_w4.batchId); - } catch (error) { - // Assert the captured error message - const expectedMessage = 'expected a string argument, found undefined'; - assert.ok(error.message.includes(expectedMessage)); - } - - console.log("coin to steal transferSend: ", coin_to_steal); - - let received_statechain_ids_w3 = undefined; - try { - received_statechain_ids_w3 = mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - } catch (error) { - // Assert the captured error message - const expectedMessage = 'num_sigs is not correct'; - assert.ok(error.message.includes(expectedMessage)); - } - - let received_statechain_ids_w4 = undefined; - try { - received_statechain_ids_w4 = await mercurynodejslib.transferReceive(clientConfig, wallet_4_name); - } catch (error) { - // Assert the captured error message - const expectedMessage = 'num_sigs is not correct'; - assert.ok(error.message.includes(expectedMessage)); - } - - try { - received_statechain_ids_w3 = await mercurynodejslib.transferReceive(clientConfig, wallet_3_name); - } catch (error) { - // Assert the captured error message - const expectedMessage = 'num_sigs is not correct'; - assert.ok(error.message.includes(expectedMessage)); - } -} - -(async () => { - - try { - const clientConfig = client_config.load(); - - // Successful test - all transfers complete within batch_time complete. - let wallet_1_name = "w_atomic_1"; - let wallet_2_name = "w_atomic_2"; - let wallet_3_name = "w_atomic_3"; - let wallet_4_name = "w_atomic_4"; - await createWallet(clientConfig, wallet_1_name); - await createWallet(clientConfig, wallet_2_name); - await createWallet(clientConfig, wallet_3_name); - await createWallet(clientConfig, wallet_4_name); - await atomicSwapSuccess(clientConfig, wallet_1_name, wallet_2_name, wallet_3_name, wallet_4_name); - console.log("Completed test for Successful test - all transfers complete within batch_time complete."); - - // Second party performs transfer-sender with incorrect or missing batch-id. First party should still receive OK. - let wallet_5_name = "w_atomic_5"; - let wallet_6_name = "w_atomic_6"; - let wallet_7_name = "w_atomic_7"; - let wallet_8_name = "w_atomic_8"; - await createWallet(clientConfig, wallet_5_name); - await createWallet(clientConfig, wallet_6_name); - await createWallet(clientConfig, wallet_7_name); - await createWallet(clientConfig, wallet_8_name); - await atomicSwapWithSecondBatchIdMissing(clientConfig, wallet_5_name, wallet_6_name, wallet_7_name, wallet_8_name); - console.log("Completed test for Second party performs transfer-sender with incorrect or missing batch-id. First party should still receive OK."); - - // First party performs transfer-sender without batch_id. - let wallet_9_name = "w_atomic_9"; - let wallet_10_name = "w_atomic_10"; - let wallet_11_name = "w_atomic_11"; - let wallet_12_name = "w_atomic_12"; - await createWallet(clientConfig, wallet_9_name); - await createWallet(clientConfig, wallet_10_name); - await createWallet(clientConfig, wallet_11_name); - await createWallet(clientConfig, wallet_12_name); - await atomicSwapWithoutFirstBatchId(clientConfig, wallet_9_name, wallet_10_name, wallet_11_name, wallet_12_name); - console.log("Completed test for First party performs transfer-sender without batch_id."); - - // One party doesn't complete transfer-receiver before the timeout. - // Both wallets should be able to repeat transfer-sender and transfer-receiver back to new addresses without error, - // after the timeout. - let wallet_13_name = "w_atomic_13"; - let wallet_14_name = "w_atomic_14"; - let wallet_15_name = "w_atomic_15"; - let wallet_16_name = "w_atomic_16"; - await createWallet(clientConfig, wallet_13_name); - await createWallet(clientConfig, wallet_14_name); - await createWallet(clientConfig, wallet_15_name); - await createWallet(clientConfig, wallet_16_name); - await atomicSwapWithTimeout(clientConfig, wallet_13_name, wallet_14_name, wallet_15_name, wallet_16_name); - console.log("Completed test for One party doesn't complete transfer-receiver before the timeout."); - - // First party tries to steal within timeout - // they perform transfer-sender a second time sending back to one of their own addresses - should fail. - let wallet_17_name = "w_atomic_17"; - let wallet_18_name = "w_atomic_18"; - let wallet_19_name = "w_atomic_19"; - let wallet_20_name = "w_atomic_20"; - await createWallet(clientConfig, wallet_17_name); - await createWallet(clientConfig, wallet_18_name); - await createWallet(clientConfig, wallet_19_name); - await createWallet(clientConfig, wallet_20_name); - await atomicSwapWithFirstPartySteal(clientConfig, wallet_17_name, wallet_18_name, wallet_19_name, wallet_20_name); - console.log("Completed test for First party tries to steal within timeout"); - - // Second party tries to steal within timeout - // they perform transfer-sender a second time sending back to one of their own addresses - should fail. - let wallet_21_name = "w_atomic_21"; - let wallet_22_name = "w_atomic_22"; - let wallet_23_name = "w_atomic_23"; - let wallet_24_name = "w_atomic_24"; - await createWallet(clientConfig, wallet_21_name); - await createWallet(clientConfig, wallet_22_name); - await createWallet(clientConfig, wallet_23_name); - await createWallet(clientConfig, wallet_24_name); - await atomicSwapWithSecondPartySteal(clientConfig, wallet_21_name, wallet_22_name, wallet_23_name, wallet_24_name); - console.log("Completed test for Second party tries to steal within timeout"); - - process.exit(0); // Exit successfully - } catch (error) { - console.error("Test encountered an error:", error); - process.exit(1); // Exit with failure - } -})(); \ No newline at end of file diff --git a/clients/apps/nodejs/test_basic_workflow.js b/clients/apps/nodejs/test_basic_workflow.js deleted file mode 100644 index 35f7303c..00000000 --- a/clients/apps/nodejs/test_basic_workflow.js +++ /dev/null @@ -1,232 +0,0 @@ -const util = require('node:util'); -const exec = util.promisify(require('node:child_process').exec); -const assert = require('node:assert/strict'); -const { CoinStatus } = require('mercurynodejslib/coin_enum'); - -async function removeDatabase() { - try { - const { stdout, stderr } = await exec('rm wallet.db'); - // console.log('stdout:', stdout); - // console.error('stderr:', stderr); - } catch (e) { - // console.error(e); - } -} - -async function createWallet(wallet_name) { - const { stdout, stderr } = await exec(`node index.js create-wallet ${wallet_name}`); - let wallet = JSON.parse(stdout); - assert.equal(wallet.name, wallet_name); - // console.log('wallet:', wallet); -} - -async function newToken(wallet_name) { - const { stdout, stderr } = await exec(`node index.js new-token ${wallet_name}`); - let json = JSON.parse(stdout); - return json; -} - -async function listTokens(wallet_name) { - const { stdout, stderr } = await exec(`node index.js list-tokens ${wallet_name}`); - let json = JSON.parse(stdout); - return json; -} - -async function getDepositBitcoinAddress(wallet_name, token_id, amount) { - const { stdout, stderr } = await exec(`node index.js new-deposit-address ${wallet_name} ${token_id} ${amount}`); - let json = JSON.parse(stdout); - return json; -} - -async function listStatecoins(wallet_name) { - try { - const { stdout, stderr } = await exec(`node index.js list-statecoins ${wallet_name}`); - let json = JSON.parse(stdout); - return json; - } catch (e) { - console.log('e:', e); - return undefined; - } -} - -async function newTransferAddress(wallet_name) { - const { stdout, stderr } = await exec(`node index.js new-transfer-address ${wallet_name}`); - let json = JSON.parse(stdout); - return json.transfer_receive; -} - -async function transferSend(wallet_name, statechain_id, to_address) { - const { stdout, stderr } = await exec(`node index.js transfer-send ${wallet_name} ${statechain_id} ${to_address}`); - let json = JSON.parse(stdout); - return json; -} - -async function transferReceive(wallet_name) { - const { stdout, stderr } = await exec(`node index.js transfer-receive ${wallet_name}`); - let json = JSON.parse(stdout); - return json; -} - -async function withdraw(wallet_name, statechain_id, to_address) { - const { stdout, stderr } = await exec(`node index.js withdraw ${wallet_name} ${statechain_id} ${to_address}`); - let json = JSON.parse(stdout); - return json.txid; -} - -async function broadcastBackupTransaction(wallet_name, statechain_id, to_address) { - const { stdout, stderr } = await exec(`node index.js broadcast-backup-transaction ${wallet_name} ${statechain_id} ${to_address}`); - let json = JSON.parse(stdout); - return json; -} - -const sleep = (ms) => { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -async function walletTransfersToItselfAndWithdraw(wallet_name) { - - const amount = 10000; - - const token = await newToken(wallet_name); - const tokenId = token.token_id; - - const deposit_info = await getDepositBitcoinAddress(wallet_name, amount); - - let tokenList = await listTokens(wallet_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - deposit_info["amount"] = amount; - console.log("deposit_coin: ", deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await listStatecoins(wallet_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - continue; - } - - coin = coinsWithStatechainId[0]; - - break; - } - - console.log("coin: ", coin); - - for (let i = 0; i < 10; i++) { - - let transfer_address = await newTransferAddress(wallet_name); - - console.log("transfer_address: ", transfer_address); - - coin = await transferSend(wallet_name, coin.statechain_id, transfer_address); - - console.log("coin transferSend: ", coin); - - let received_statechain_ids = await transferReceive(wallet_name); - - console.log("received_statechain_ids: ", received_statechain_ids); - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); - } - - let withdraw_address = "tb1qwrujs6f4gyexsextpf9p50smjtht7p7ypknteu"; - - let txid = await withdraw(wallet_name, coin.statechain_id, withdraw_address); - - console.log("txid: ", txid); - -}; - -async function walletTransfersMultipleTimesToItselfAndBroadcastsBackup(wallet_name) { - for (let i = 0; i < 3; i++) { - await walletTransfersToItselfAndWithdraw(wallet_name); - } -} - -async function walletTransfersToAnotherAndBroadcastsBackupTx(wallet_1_name, wallet_2_name) { - - const amount = 10000; - - const token = await newToken(wallet_1_name); - const tokenId = token.token_id; - - const deposit_info = await getDepositBitcoinAddress(wallet_1_name, amount); - - deposit_info["amount"] = amount; - console.log("deposit_info w1: ", deposit_info); - - let tokenList = await listTokens(wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - console.log("usedToken: ", usedToken); - - assert(usedToken.spent); - - let coin = undefined; - - while (!coin) { - const list_coins = await listStatecoins(wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(5000); - continue; - } - - coin = coinsWithStatechainId[0]; - - break; - } - - let transfer_address = await newTransferAddress(wallet_2_name); - - coin = await transferSend(wallet_1_name, coin.statechain_id, transfer_address); - - let received_statechain_ids = await transferReceive(wallet_2_name); - - console.log("received_statechain_ids: ", received_statechain_ids); - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); - - let withdraw_address = "tb1qwrujs6f4gyexsextpf9p50smjtht7p7ypknteu"; - - let txids = await broadcastBackupTransaction(wallet_2_name, received_statechain_ids[0], withdraw_address); - - console.log("txids: ", txids); - -} - -(async () => { - let wallet_1_name = "w1"; - let wallet_2_name = "w2"; - - await removeDatabase(); - await createWallet(wallet_1_name); - await createWallet(wallet_2_name); - - await walletTransfersMultipleTimesToItselfAndBroadcastsBackup(wallet_1_name); - - await walletTransfersToAnotherAndBroadcastsBackupTx(wallet_1_name, wallet_2_name) - - await removeDatabase(); -})(); diff --git a/clients/apps/nodejs/test_basic_workflow2.js b/clients/apps/nodejs/test_basic_workflow2.js deleted file mode 100644 index faf64184..00000000 --- a/clients/apps/nodejs/test_basic_workflow2.js +++ /dev/null @@ -1,1072 +0,0 @@ -const assert = require('node:assert/strict'); -const mercurynodejslib = require('mercurynodejslib'); -const { CoinStatus } = require('mercurynodejslib/coin_enum'); -const client_config = require('./client_config'); -const sqlite_manager = require('../../libs/nodejs/sqlite_manager'); -const mercury_wasm = require('mercury-wasm'); -const transaction = require('../../libs/nodejs/transaction'); -const utils = require('../../libs/nodejs/utils'); -const { getDatabase, sleep, createWallet, getElectrumClient, generateBlock, depositCoin, connectElectr, disconnectElectr, disconnectMercuryServer, connectMercuryServer } = require('./test_utils'); - -async function walletTransfersToItselfAndWithdraw(clientConfig, wallet_name) { - - const token = await mercurynodejslib.newToken(clientConfig, wallet_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_name); - // console.log(list_coins); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - // console.log("Waiting for coin to be confirmed..."); - // console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(1000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - - break; - } - - for (let i = 0; i < 10; i++) { - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_name, null); - - coin = await mercurynodejslib.transferSend(clientConfig, wallet_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_name); - let received_statechain_ids = transferReceiveResult.receivedStatechainIds; - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); - } - - let withdraw_address = "bcrt1qgh48u8aj4jvjkalc28lqujyx2wveck4jsm59x9"; - - let txid = await mercurynodejslib.withdrawCoin(clientConfig, wallet_name, coin.statechain_id, withdraw_address, null, null); - - // TODO: confirm withdrawal status -} - -async function walletTransfersToItselfTillLocktimeReachesBlockHeightAndWithdraw(clientConfig, wallet_name) { - - const token = await mercurynodejslib.newToken(clientConfig, wallet_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - /* console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); */ - await sleep(5000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - - break; - } - - const electrumClient = await getElectrumClient(clientConfig); - - let block_header = await electrumClient.request('blockchain.headers.subscribe'); - let currentBlockHeight = block_header.height; - - while (coin.locktime <= currentBlockHeight) { - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_name, null); - - coin = await mercurynodejslib.transferSend(clientConfig, wallet_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_name); - let received_statechain_ids = transferReceiveResult.receivedStatechainIds; - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); - - // Fetch the coin again to get the updated locktime - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_name); - coin = list_coins.find(c => c.statechain_id === coin.statechain_id); - } - - let withdraw_address = "bcrt1qgh48u8aj4jvjkalc28lqujyx2wveck4jsm59x9"; - - let txid = await mercurynodejslib.withdrawCoin(clientConfig, wallet_name, coin.statechain_id, withdraw_address, null, null); - - // TODO: confirm withdrawal status -} - -async function walletTransfersToAnotherAndBroadcastsBackupTx(clientConfig, wallet_1_name, wallet_2_name) { - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - /* console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); */ - await sleep(1000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - - break; - } - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - let received_statechain_ids = transferReceiveResult.receivedStatechainIds; - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); - - let withdraw_address = "bcrt1qgh48u8aj4jvjkalc28lqujyx2wveck4jsm59x9"; - - let txid = await mercurynodejslib.broadcastBackupTransaction(clientConfig, wallet_2_name, coin.statechain_id, withdraw_address, null); - - // TODO: confirm withdrawal status -} - -async function depositAndRepeatSend(clientConfig, wallet_1_name) { - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - // console.log("Waiting for coin to be confirmed..."); - // console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(1000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - break; - } - - for (let i = 0; i < 10; i++) { - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_1_name, null); - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_1_name); - let received_statechain_ids = transferReceiveResult.receivedStatechainIds; - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); - } - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_1_name, null); - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_1_name); - let received_statechain_ids = transferReceiveResult.receivedStatechainIds; - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); -} - -async function transferSenderAfterTransferReceiver(clientConfig, wallet_1_name, wallet_2_name) { - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - // console.log("Waiting for coin to be confirmed..."); - // console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(1000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - break; - } - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - let received_statechain_ids = transferReceiveResult.receivedStatechainIds; - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); - - try { - transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - assert.fail("Expected error when transferring from wallet one again, but no error was thrown"); - } catch (error) { - console.log("Expected error received: ", error.message); - assert(error.message.includes("Coin status must be CONFIRMED or IN_TRANSFER to transfer it. The current status is TRANSFERRED"), - `Unexpected error message: ${error.message}`); - } -} - -async function depositAndTransfer(clientConfig, wallet_name) { - - for (let i = 0; i < 10; i++) { - const token = await mercurynodejslib.newToken(clientConfig, wallet_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - // console.log("Waiting for coin to be confirmed..."); - // console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(1000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - - break; - } - } - - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_name); - - for (let coin of list_coins) { - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_name, null); - - coin = await mercurynodejslib.transferSend(clientConfig, wallet_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_name); - let received_statechain_ids = transferReceiveResult.receivedStatechainIds; - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); - } -} - -async function interruptBeforeSignFirst(clientConfig, wallet_1_name, wallet_2_name) { - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - // console.log("Waiting for coin to be confirmed..."); - // console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(1000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - break; - } - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - console.log("Disconnect mercurylayer-mercury-1 from network"); - await disconnectMercuryServer(); - - try { - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - assert.fail("Expected error when transferring from wallet one, but no error was thrown"); - } catch (error) { - console.log("Expected error received: ", error.message); - assert(error.message.includes("connect ECONNREFUSED 0.0.0.0:8000"), - `Unexpected error message: ${error.message}`); - } - console.log("Connect mercurylayer-mercury-1 from network"); - await connectMercuryServer(); -} - -const new_transaction = async(clientConfig, electrumClient, coin, toAddress, isWithdrawal, qtBackupTx, block_height, network) => { - let coin_nonce = mercury_wasm.createAndCommitNonces(coin); - - let server_pubnonce = await transaction.signFirst(clientConfig, coin_nonce.sign_first_request_payload); - - coin.secret_nonce = coin_nonce.secret_nonce; - coin.public_nonce = coin_nonce.public_nonce; - coin.server_public_nonce = server_pubnonce; - coin.blinding_factor = coin_nonce.blinding_factor; - - const serverInfo = await utils.infoConfig(clientConfig, electrumClient); - - let new_block_height = 0; - if (block_height == null) { - const block_header = await electrumClient.request('blockchain.headers.subscribe'); // request(promise) - new_block_height = block_header.height; - } else { - new_block_height = block_height; - } - - const initlock = serverInfo.initlock; - const interval = serverInfo.interval; - const feeRateSatsPerByte = serverInfo.fee_rate_sats_per_byte; - - let partialSigRequest = mercury_wasm.getPartialSigRequest( - coin, - new_block_height, - initlock, - interval, - feeRateSatsPerByte, - qtBackupTx, - toAddress, - network, - isWithdrawal); - - const serverPartialSigRequest = partialSigRequest.partial_signature_request_payload; - - console.log("Disconnect mercurylayer-mercury-1 from network"); - await disconnectMercuryServer(); - - let serverPartialSig; - - try { - serverPartialSig = await transaction.signSecond(clientConfig, serverPartialSigRequest); - assert.fail("Expected error when signing second transaction, but no error was thrown"); - } catch (error) { - console.log("Expected error received: ", error.message); - assert(error.message.includes("Server partial signature is not available."), - `Unexpected error message: ${error.message}`); - } - - console.log("Connect mercurylayer-mercury-1 from network"); - await connectMercuryServer(); -} - -async function interruptBeforeSignSecond(clientConfig, wallet_1_name, wallet_2_name) { - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coinDeposited = undefined; - - while (!coinDeposited) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - // console.log("Waiting for coin to be confirmed..."); - // console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(1000); - generateBlock(1); - continue; - } - - coinDeposited = coinsWithStatechainId[0]; - break; - } - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - const db = await getDatabase(clientConfig); - - const electrumClient = await getElectrumClient(clientConfig); - - let options = transfer_address; - - let batchId = (options && options.batch_id) || null; - - let wallet = await sqlite_manager.getWallet(db, wallet_1_name); - - const backupTxs = await sqlite_manager.getBackupTxs(db, coinDeposited.statechain_id); - - if (backupTxs.length === 0) { - throw new Error(`There is no backup transaction for the statechain id ${coinDeposited.statechain_id}`); - } - - const new_tx_n = backupTxs.length + 1; - - let coinsWithStatechainId = wallet.coins.filter(c => { - return c.statechain_id === coinDeposited.statechain_id - }); - - if (!coinsWithStatechainId || coinsWithStatechainId.length === 0) { - throw new Error(`There is no coin for the statechain id ${coinDeposited.statechain_id}`); - } - - // If the user sends to himself, he will have two coins with same statechain_id - // In this case, we need to find the one with the lowest locktime - // Sort the coins by locktime in ascending order and pick the first one - let coin = coinsWithStatechainId.sort((a, b) => a.locktime - b.locktime)[0]; - - if (coin.status != CoinStatus.CONFIRMED && coin.status != CoinStatus.IN_TRANSFER) { - throw new Error(`Coin status must be CONFIRMED or IN_TRANSFER to transfer it. The current status is ${coin.status}`); - } - - if (coin.locktime == null) { - throw new Error("Coin.locktime is null"); - } - - const blockHeader = await electrumClient.request('blockchain.headers.subscribe'); // request(promise) - const currentBlockheight = blockHeader.height; - - if (currentBlockheight > coin.locktime) { - throw new Error(`The coin is expired. Coin locktime is ${coin.locktime} and current blockheight is ${currentBlockheight}`); - } - - const statechain_id = coin.statechain_id; - const signed_statechain_id = coin.signed_statechain_id; - - const isWithdrawal = false; - const qtBackupTx = backupTxs.length; - - backupTxs.sort((a, b) => a.tx_n - b.tx_n); - - const bkp_tx1 = backupTxs[0]; - - const block_height = mercury_wasm.getBlockheight(bkp_tx1); - - const decodedTransferAddress = mercury_wasm.decodeTransferAddress(transfer_address.transfer_receive); - const new_auth_pubkey = decodedTransferAddress.auth_pubkey; - - // const new_x1 = await get_new_x1(clientConfig, statechain_id, signed_statechain_id, new_auth_pubkey, batchId); - - const signed_tx = await new_transaction(clientConfig, electrumClient, coin, transfer_address.transfer_receive, isWithdrawal, qtBackupTx, block_height, wallet.network); - - transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - - console.log("coin ", coin); - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - let received_statechain_ids = transferReceiveResult.receivedStatechainIds; - - console.log("received_statechain_ids: ", received_statechain_ids); - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); - - // Coin withdrawal - let withdraw_address = "bcrt1qgh48u8aj4jvjkalc28lqujyx2wveck4jsm59x9"; - - let txid = await mercurynodejslib.withdrawCoin(clientConfig, wallet_2_name, coin.statechain_id, withdraw_address, null, null); - - console.log("txid: ", txid); -} - -async function interruptSignWithElectrumUnavailability(clientConfig, wallet_1_name, wallet_2_name) { - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - // console.log("Waiting for coin to be confirmed..."); - // console.log(`Check the address ${deposit_info.deposit_address} ...\n`); - await sleep(1000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - break; - } - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - await sleep(5000); // wait for Electrum to disconnect - - console.log("Disconnect mercurylayer-electrs-1 from network"); - await disconnectElectr(); - - try { - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - assert.fail("Expected error when transferring from wallet one, but no error was thrown"); - } catch (error) { - console.log("Expected error received: ", error.message); - assert(error.message.includes("connect ECONNREFUSED 0.0.0.0:50001"), - `Unexpected error message: ${error.message}`); - } - console.log("Connect mercurylayer-electrs-1 from network"); - await connectElectr(); - - await sleep(5000); // wait for Electrum to connect -} - -async function interruptTransferReceiveWithElectrumUnavailability(clientConfig, wallet_1_name, wallet_2_name) { - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - /* console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); */ - await sleep(1000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - break; - } - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - - await sleep(5000); // wait for Electrum to disconnect - - console.log("Disconnect mercurylayer-electrs-1 from network"); - await disconnectElectr(); - - try { - await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - assert.fail("Expected error when receiving into wallet two, but no error was thrown"); - } catch (error) { - console.log("Expected error received: ", error.message); - assert(error.message.includes("connect ECONNREFUSED 0.0.0.0:50001"), - `Unexpected error message: ${error.message}`); - } - console.log("Connect mercurylayer-electrs-1 from network"); - await connectElectr(); - - await sleep(5000); // wait for Electrum to connect -} - -async function interruptTransferReceiveWithMercuryServerUnavailability(clientConfig, wallet_1_name, wallet_2_name) { - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - /* console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); */ - await sleep(5000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - break; - } - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - - console.log("Disconnect mercurylayer-mercury-1 from network"); - await disconnectMercuryServer(); - - try { - let received_statechain_ids = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - assert.fail("Expected error when receiving into wallet two, but no error was thrown"); - } catch (error) { - console.log("Expected error received: ", error.message); - assert(error.message.includes("connect ECONNREFUSED 0.0.0.0:8000"), - `Unexpected error message: ${error.message}`); - } - console.log("Connect mercurylayer-mercury-1 from network"); - await connectMercuryServer(); -} - -async function transferSendAtCoinExpiry(clientConfig, wallet_1_name, wallet_2_name) { - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - /* console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); */ - await sleep(1000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - break; - } - - const electrumClient = await getElectrumClient(clientConfig); - - const blockHeader = await electrumClient.request('blockchain.headers.subscribe'); // request(promise) - const currentBlockheight = blockHeader.height; - - const blocksToBeGenerated = coin.locktime - currentBlockheight; - await generateBlock(blocksToBeGenerated); - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - try { - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - assert.fail("Expected error when transferring expired coin, but no error was thrown"); - } catch (error) { - console.log("Expected error received: ", error.message); - assert(error.message.includes("The coin is expired."), - `Unexpected error message: ${error.message}`); - } -} - -async function transferReceiveAtCoinExpiry(clientConfig, wallet_1_name, wallet_2_name) { - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - /* console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); */ - await sleep(5000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - break; - } - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - - const electrumClient = await getElectrumClient(clientConfig); - - const blockHeader = await electrumClient.request('blockchain.headers.subscribe'); // request(promise) - const currentBlockheight = blockHeader.height; - - const blocksToBeGenerated = coin.locktime - currentBlockheight; - await generateBlock(blocksToBeGenerated); - - let errorMessage; - console.error = (msg) => { - errorMessage = msg; - }; - - let transferReceiveResult = await mercurynodejslib.transferReceive(clientConfig, wallet_2_name); - let received_statechain_ids = transferReceiveResult.receivedStatechainIds; - - // Assert the captured error message - const expectedMessage = 'The coin is expired.'; - assert.ok(errorMessage.includes(expectedMessage)); - - assert(received_statechain_ids.length > 0); - assert(received_statechain_ids[0] == coin.statechain_id); -} - -async function transferSendCoinExpiryBySending(clientConfig, wallet_1_name, wallet_2_name) { - - const token = await mercurynodejslib.newToken(clientConfig, wallet_1_name); - const tokenId = token.token_id; - - const amount = 10000; - const deposit_info = await mercurynodejslib.getDepositBitcoinAddress(clientConfig, wallet_1_name, amount); - - let tokenList = await mercurynodejslib.getWalletTokens(clientConfig, wallet_1_name); - - let usedToken = tokenList.find(token => token.token_id === tokenId); - - assert(usedToken.spent); - - await depositCoin(clientConfig, wallet_1_name, amount, deposit_info); - - let coin = undefined; - - while (!coin) { - const list_coins = await mercurynodejslib.listStatecoins(clientConfig, wallet_1_name); - - let coinsWithStatechainId = list_coins.filter(c => { - return c.statechain_id === deposit_info.statechain_id && c.status === CoinStatus.CONFIRMED; - }); - - if (coinsWithStatechainId.length === 0) { - /* console.log("Waiting for coin to be confirmed..."); - console.log(`Check the address ${deposit_info.deposit_address} ...\n`); */ - await sleep(5000); - generateBlock(1); - continue; - } - - coin = coinsWithStatechainId[0]; - break; - } - - const electrumClient = await getElectrumClient(clientConfig); - - const blockHeader = await electrumClient.request('blockchain.headers.subscribe'); // request(promise) - const currentBlockheight = blockHeader.height; - - const serverInfo = await utils.infoConfig(clientConfig, electrumClient); - - const blocksToBeGenerated = coin.locktime - currentBlockheight - serverInfo.interval; - await generateBlock(blocksToBeGenerated); - - let transfer_address = await mercurynodejslib.newTransferAddress(clientConfig, wallet_2_name, null); - - try { - coin = await mercurynodejslib.transferSend(clientConfig, wallet_1_name, coin.statechain_id, transfer_address.transfer_receive, false, null); - assert.fail("Expected error when transferring expired coin, but no error was thrown"); - } catch (error) { - console.log("Expected error received: ", error.message); - assert(error.message.includes("The coin is expired."), - `Unexpected error message: ${error.message}`); - } -} - -(async () => { - - try { - const clientConfig = client_config.load(); - - let wallet_1_name = "w1"; - let wallet_2_name = "w2"; - await createWallet(clientConfig, wallet_1_name); - await createWallet(clientConfig, wallet_2_name); - await walletTransfersToItselfAndWithdraw(clientConfig, wallet_1_name); - // await walletTransfersToAnotherAndBroadcastsBackupTx(clientConfig, wallet_1_name, wallet_2_name); - - - // Deposit, repeat send - let wallet_3_name = "w3"; - let wallet_4_name = "w4"; - await createWallet(clientConfig, wallet_3_name); - await createWallet(clientConfig, wallet_4_name); - await depositAndRepeatSend(clientConfig, wallet_3_name); - console.log("Completed test for Deposit, repeat send"); - - // Transfer-sender after transfer-receiver - let wallet_5_name = "w5"; - let wallet_6_name = "w6"; - await createWallet(clientConfig, wallet_5_name); - await createWallet(clientConfig, wallet_6_name); - await transferSenderAfterTransferReceiver(clientConfig, wallet_5_name, wallet_6_name); - console.log("Completed test for Transfer-sender after transfer-receiver"); - - // Deposit of 10 coins in same wallet, and transfer each one 10 times - let wallet_7_name = "w7"; - await createWallet(clientConfig, wallet_7_name); - await depositAndTransfer(clientConfig, wallet_7_name); - console.log("Completed test for Deposit of 100 coins in same wallet, and transfer each one 100 times"); - - // Test for interruption of transferSend before sign first - let wallet_8_name = "w8"; - let wallet_9_name = "w9"; - await createWallet(clientConfig, wallet_8_name); - await createWallet(clientConfig, wallet_9_name); - await interruptBeforeSignFirst(clientConfig, wallet_8_name, wallet_9_name); - console.log("Completed test for interruption of transferSend before sign first"); - - // Test for interruption of transferSend before sign second - let wallet_10_name = "w10"; - let wallet_11_name = "w11"; - await createWallet(clientConfig, wallet_10_name); - await createWallet(clientConfig, wallet_11_name); - await interruptBeforeSignSecond(clientConfig, wallet_10_name, wallet_11_name); - console.log("Completed test for interruption of transferSend before sign second"); - - // Test for interruption of sign with Electrum unavailability - let wallet_12_name = "w12"; - let wallet_13_name = "w13"; - await createWallet(clientConfig, wallet_12_name); - await createWallet(clientConfig, wallet_13_name); - await interruptSignWithElectrumUnavailability(clientConfig, wallet_12_name, wallet_13_name); - console.log("Completed test for interruption of sign with Electrum unavailability"); - - // Test for interruption of transfer receive with Electrum unavailability - let wallet_14_name = "w14"; - let wallet_15_name = "w15"; - await createWallet(clientConfig, wallet_14_name); - await createWallet(clientConfig, wallet_15_name); - await interruptTransferReceiveWithElectrumUnavailability(clientConfig, wallet_14_name, wallet_15_name); - console.log("Completed test for interruption of transfer receive with Electrum unavailability"); - - // Test for interruption of transfer receive with mercury server unavailability - let wallet_16_name = "w16"; - let wallet_17_name = "w17"; - await createWallet(clientConfig, wallet_16_name); - await createWallet(clientConfig, wallet_17_name); - await interruptTransferReceiveWithMercuryServerUnavailability(clientConfig, wallet_16_name, wallet_17_name); - console.log("Completed test for interruption of transfer receive with mercury server unavailability"); - - // Deposit, iterative self transfer - let wallet_18_name = "w18"; - await createWallet(clientConfig, wallet_18_name); - await walletTransfersToItselfTillLocktimeReachesBlockHeightAndWithdraw(clientConfig, wallet_18_name); - console.log("Completed test for Deposit, iterative self transfer"); - - // Send backup tx before expiry - let wallet_19_name = "w19"; - let wallet_20_name = "w20"; - await createWallet(clientConfig, wallet_19_name); - await createWallet(clientConfig, wallet_20_name); - try { - await walletTransfersToAnotherAndBroadcastsBackupTx(clientConfig, wallet_19_name, wallet_20_name) - assert.fail("Expected error when sending backup tx before expiry, but no error was thrown"); - } catch (error) { - console.log("Expected error received: ", error.message); - assert(error.message.includes("The coin is not expired yet."), - `Unexpected error message: ${error.message}`); - } - console.log("Completed test for send backup tx before expiry"); - - // Transfer-sender of coin at expiry - let wallet_21_name = "w21"; - let wallet_22_name = "w22"; - await createWallet(clientConfig, wallet_21_name); - await createWallet(clientConfig, wallet_22_name); - await transferSendAtCoinExpiry(clientConfig, wallet_21_name, wallet_22_name); - console.log("Completed test for Transfer-sender of coin at expiry"); - - // Transfer-receive of coin at expiry - let wallet_23_name = "w23"; - let wallet_24_name = "w24"; - await createWallet(clientConfig, wallet_23_name); - await createWallet(clientConfig, wallet_24_name); - await transferReceiveAtCoinExpiry(clientConfig, wallet_23_name, wallet_24_name); - console.log("Completed test for Transfer-receive of coin at expiry"); - - // Transfer-sender of coin that will make it expired by sending - let wallet_25_name = "w25"; - let wallet_26_name = "w26"; - await createWallet(clientConfig, wallet_25_name); - await createWallet(clientConfig, wallet_26_name); - await transferSendCoinExpiryBySending(clientConfig, wallet_25_name, wallet_26_name); - console.log("Completed test for Transfer-sender of coin that will make it expired by sending"); - - process.exit(0); // Exit successfully - } catch (error) { - console.error("Test encountered an error:", error); - process.exit(1); // Exit with failure - } -})(); From a728bb66dcc4878a7643b8df7d64f8f8605467c6 Mon Sep 17 00:00:00 2001 From: Tom Trevethan Date: Fri, 6 Sep 2024 17:00:11 +0100 Subject: [PATCH 7/7] Update tnc.html --- token-server/tnc.html | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/token-server/tnc.html b/token-server/tnc.html index 13721532..d96e0a0c 100644 --- a/token-server/tnc.html +++ b/token-server/tnc.html @@ -1,12 +1,13 @@ -Users of the api.mercurylayer.com blind key service should carefully read the terms of use detailed below. By completing token_init with the supplied token_id or accessing our services a User agrees to be bound by these Terms of Use. These Terms of User are not assignable by the user to anyone else. +Users of the api.mercurylayer.com blind key service should carefully read the terms of use detailed below. By completing token_init with the supplied token_id or accessing our services a User agrees to be bound by these Terms of Use. These Terms of use are not assignable by the user to anyone else. Mercury layer is an implementation of a system the uses a blind co-signing and key-update service that enables statechains. -The Mercury blind key service generates and updates key shares (or key fragments) on request in addition to a count of partial blinded signatures. The blind key-update server never has control or custody, and is never aware of the identity of any shared key. +The Mercury blind key service generates and updates key shares on request in addition to partial blinded signatures. The blind key-update server never has control or custody, and is never aware of the identity of any shared key. + +Mercury layer service: -Mercury layer service The mercury layer service generates a private key share s1 on initialisation of a session. In order to initialise a session, a client must provide a valid token_id which controls access to the service. -The client then initialises a session with an auth_pubkey which is used to authenticate all subsequent messages with the server. The server responds with the public elliptic curve point corresponding to the session private key share s1. +The client then initialises a session with an auth_pubkey which is used to authenticate all subsequent messages with the server. The server responds with the public key corresponding to the session private key share s1. Once initialised, the server can then perform two operations using the key share: