├── .babelrc ├── .circleci ├── bring-gamma.sh ├── chrome-deps ├── config.yml ├── install-current-node.sh ├── list-chrome-deps.js └── main.sh ├── .gitignore ├── LICENSE ├── LICENSE-HEADER ├── NETWORK-TOU.md ├── README.md ├── e2e ├── browser │ ├── browser.test.js │ └── index.html ├── contract │ ├── increment_base.go │ ├── increment_functions.go │ └── increment_functions_test.go ├── gamma-driver.js └── nodejs │ └── e2e.test.js ├── jest-puppeteer.config.js ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── codec │ ├── Arguments.ts │ ├── Events.ts │ ├── ExecutionResult.ts │ ├── NetworkType.ts │ ├── OpGetBlock.ts │ ├── OpGetTransactionReceiptProof.ts │ ├── OpGetTransactionStatus.ts │ ├── OpRunQuery.ts │ ├── OpSendTransaction.ts │ ├── RequestStatus.ts │ ├── TransactionStatus.ts │ └── contract.test.ts ├── crypto │ ├── Digest.test.ts │ ├── Digest.ts │ ├── Encoding.test.ts │ ├── Encoding.ts │ ├── Hash.test.ts │ ├── Hash.ts │ ├── Keys.test.ts │ ├── Keys.ts │ ├── Signer.test.ts │ └── Signer.ts ├── index.ts ├── lib.ts ├── matcher-extensions.d.ts ├── matcher-extensions.js ├── orbs │ ├── Account.ts │ ├── Client.test.ts │ └── Client.ts ├── protocol │ ├── Base.ts │ ├── Client.ts │ └── Protocol.ts └── types │ ├── bigint.d.ts │ ├── externals.d.ts │ ├── get-random-values.d.ts │ └── text-encoding.d.ts ├── test.sh ├── tsconfig-for-types.json ├── tsconfig.json ├── tslint.json └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/env", { "modules": false }], "@babel/typescript"], 3 | "plugins": [ 4 | "@babel/plugin-transform-runtime", 5 | "@babel/plugin-proposal-class-properties", 6 | "@babel/plugin-proposal-object-rest-spread" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.circleci/bring-gamma.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # This bash script downloads and installs a release pre-built gamma-cli 3 | 4 | GAMMA_CLI_VERSION="v0.6.3" 5 | GAMMA_CLI_URL="https://github.com/orbs-network/gamma-cli/releases/download/$GAMMA_CLI_VERSION/gammacli-linux-x86-64-$GAMMA_CLI_VERSION.tar.gz" 6 | 7 | echo "Downloading pre-built gamma-cli ($GAMMA_CLI_VERSION) from it's official GitHub release repository.." 8 | wget $GAMMA_CLI_URL 9 | tar -zxvf gammacli*.tar.gz 10 | sudo mv _bin/gamma-cli /usr/bin/gamma-cli && echo "gamma-cli successfully installed" 11 | 12 | gamma-cli 13 | 14 | exit 0 -------------------------------------------------------------------------------- /.circleci/chrome-deps: -------------------------------------------------------------------------------- 1 | gconf-service 2 | libasound2 3 | libatk1.0-0 4 | libatk-bridge2.0-0 5 | libc6 6 | libcairo2 7 | libcups2 8 | libdbus-1-3 9 | libexpat1 10 | libfontconfig1 11 | libgcc1 12 | libgconf-2-4 13 | libgdk-pixbuf2.0-0 14 | libglib2.0-0 15 | libgtk-3-0 16 | libnspr4 17 | libpango-1.0-0 18 | libpangocairo-1.0-0 19 | libstdc++6 20 | libx11-6 21 | libx11-xcb1 22 | libxcb1 23 | libxcomposite1 24 | libxcursor1 25 | libxdamage1 26 | libxext6 27 | libxfixes3 28 | libxi6 29 | libxrandr2 30 | libxrender1 31 | libxss1 32 | libxtst6 33 | ca-certificates 34 | fonts-liberation 35 | libappindicator1 36 | libnss3 37 | lsb-release 38 | xdg-utils 39 | wget -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | machine: true 5 | steps: 6 | - checkout 7 | - run: ./.circleci/install-current-node.sh 8 | - run: sudo apt-get update && sudo apt-get install -y `node ~/repo/.circleci/list-chrome-deps.js` 9 | - run: ./.circleci/bring-gamma.sh 10 | - run: ./.circleci/main.sh 11 | -------------------------------------------------------------------------------- /.circleci/install-current-node.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash 4 | 5 | export NVM_DIR="/opt/circleci/.nvm" 6 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm 7 | [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion 8 | 9 | nvm install 11.7 10 | -------------------------------------------------------------------------------- /.circleci/list-chrome-deps.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | 6 | const result = fs.readFileSync(path.join(__dirname, 'chrome-deps')); 7 | 8 | console.log(result.toString().split('\n').join(' ')); -------------------------------------------------------------------------------- /.circleci/main.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export NVM_DIR="/opt/circleci/.nvm" 4 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm 5 | [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion 6 | 7 | nvm use 11.7 8 | npm install 9 | bash test.sh 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | *.swp 10 | 11 | pids 12 | logs 13 | results 14 | tmp 15 | 16 | contract 17 | 18 | # Build 19 | public/css/main.css 20 | .rpt2_cache 21 | 22 | # Coverage reports 23 | coverage 24 | 25 | # API keys and secrets 26 | .env 27 | 28 | # Dependency directory 29 | node_modules 30 | bower_components 31 | 32 | # Editors 33 | .idea 34 | *.iml 35 | 36 | # OS metadata 37 | .DS_Store 38 | Thumbs.db 39 | 40 | # Ignore built ts files 41 | dist/**/* 42 | 43 | orbs-test-keys.json -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Orbs Network 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE-HEADER: -------------------------------------------------------------------------------- 1 | Copyright 2019 the orbs-client-sdk-javascript authors 2 | This file is part of the orbs-client-sdk-javascript library in the Orbs project. 3 | 4 | This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 5 | The above notice should be included in all copies or substantial portions of the software. 6 | -------------------------------------------------------------------------------- /NETWORK-TOU.md: -------------------------------------------------------------------------------- 1 | # ORBS NETWORK TERMS OF USE 2 | 3 | These Terms of Use (“__Terms__”) are a multi-party contract among you and all other participants in the current and future decentralized, blockchain infrastructure-as-a-service network, branded “Orbs” and made available in open source code form at the GitHub repository locates at [https://github.com/orbs-network](https://github.com/orbs-network) (the “__Network__”), including without limitation the Network’s: (1) consensus-based decentralized computing services, (2) consensus-based decentralized storage services, (3) consensus-as-a-service services, and (4) security, governance and operation model, all of which are provided on or by way of the Network (collectively, the “__Services__”). The Network operates using cryptocurrency tokens to be used exclusively in connection with the Network (“__Orbs Tokens__”). These Terms apply to all participants in the Network, including: (i) developers (both individuals and entities) that will run decentralized applications over the Network (“__Developers__”); (ii) the individuals and entities that are the end-users of such applications or that otherwise interact directly or indirectly with the Network (“__End-Users__”); (iii) the servers that participate in the consensus process and provide the actual compute and storage resources to execute Developers’ applications on top of the Network’s blockchain infrastructure (“__Validators__”); (iv) the persons and entities that, under the Network’s security, governance and operation model, review Validators, monitor their operations and approve and elect Validators (“__Guardians__”); (v) holders of Orbs Tokens (“__Token Holders__”); and (vi) any and all entities and persons who created and/or initially sold Orbs Tokens and their respective current or future subsidiaries, affiliates, directors, officers, employees, agents, representatives, and any other person or entity with any involvement in the Network’s reserve allocation or in developing software underlying the Network, in each case, or any other such person or entity, including without limitation Orbs Ltd. (collectively, the “__Subject Persons__”). All users of and participants in the Network, including Guardians, Validators, Developers and End-Users will collectively be referred to as “__you__” or “__your__.” Your use of and access to the Network and any Services or applications available on the Network, and any information, text, photos, graphics, videos, idea, concept, discovery, invention, development, technology, algorithm, program, code, documentation or other material or information available on or through the Network is subject to these Terms. 4 | 5 | These Terms are a legal agreement, and they contain important information on your legal rights, remedies and obligations. You may use the Network only if you can form a binding contract. 6 | 7 | Please read and review these Terms carefully. 8 | 9 | If you are using the Network as a natural person, by using the Network (i) you agree that you have read, understood and are bound by these Terms; (ii) you will comply with all applicable laws, regulations, rules and policies; and (iii) you represent that you are an adult and have the legal capacity to enter a contract in the jurisdiction where you reside, and are of the minimum age required by the law of your jurisdiction to engage in activity of the type you will engage in on the Network, including entering into a binding agreement to abide by these Terms. You also agree that your access to and use of the Network is a valuable benefit that you receive by agreeing to and complying with these Terms. If you do not agree to these Terms, you may not access or use the Network. 10 | 11 | If you are using the Network as a natural person representing a legal entity, by using the Network, in addition to the foregoing undertakings, you represent and warrant on behalf of such entity that: (i) you are authorized to act on the Network on behalf of such entity, including accepting these Terms; (ii) such entity is duly organized, validly existing and in good standing under the laws of the jurisdiction of its formation; (iii) such entity has all requisite power and authority to enter into these Terms and to consummate the transactions contemplated hereby; (iv) such entity has duly and properly taken all corporate acts and other proceedings required to be taken to authorize the execution and performance of these Terms and to consummate the transactions contemplated hereby; (v) such entity is in compliance with all applicable laws and will not use the Network for or in connection with any unlawful act or purpose; and (vi) the use and operation of any content and materials that such entity may contribute to the Network does not and will not infringe, misappropriate or conflict with any Intellectual Property or other right of any third party. If you do not agree to these Terms and such entity is not able to make the foregoing representations and warranties, you may not use or access the network. 12 | 13 | Minors Prohibited: The Network is not directed to individuals under the age of eighteen ((18) or the age of majority in your jurisdiction if the age of majority is greater). If you are under the age of eighteen or the age of majority (if greater), you are not authorized to access or use the Network. 14 | 15 | ## 1. Overview of the Orbs Network 16 | The Network is a peer-to-peer platform with a decentralized, blockchain-based architecture designed to provide blockchain infrastructure-as-a-service. The Network offers the Services. The participants in the Network are Developers, End-Users, Guardians, Validators and Token Holders. 17 | 18 | You hereby expressly acknowledge and agree that the Network is a decentralized network and the Subject Persons: (A) are not responsible for the development or launch of the Network and (B) do not undertake any responsibility to operate, maintain, support or otherwise authorize any activity related to the Network. 19 | 20 | As a decentralized network, the Network and the Network Content (as defined below) may be updated or modified from time to time. Such modifications or updates may be significant, including the adoption of new versions of the Network Content that differ substantially from the current version and result in significant changes to the Network. Such changes may include updates or the implementation of a more advanced version of the Network’s consensus algorithm, fee model, smart contract capabilities, security, governance and operation model or other features of the Network. 21 | 22 | Such updates or modifications may be proposed by the Subject Persons, Guardians, Validators or other persons or entities who desire to make such proposals. The acceptance of such proposals may be subject to approval in accordance with the terms of the Network’s then-applicable security, governance and operation model. Alternatively, in the case of certain upgrades to the security, governance and operation model or changes that otherwise supersede or are not technically implementable within the Network’s then-applicable security, governance and operation model, the acceptance of such changes may depend on the practical decision by Guardians, Validators, Token Holders, Developers and End-Users to implement such proposals or adopt the version of the Network containing such proposals or to decline to do so. 23 | 24 | ## 2. Ownership 25 | “Network Content” includes, without limitation, the Orbs software stack reference implementation, including any idea, concept, discovery, invention, development, technology, algorithm, program, code, documentation or other material or information related thereto; the look and feel, design, layout, organization, presentation, user interface, navigation and stylistic conventions of the Network; trademarks, trade names, and all other intellectual property rights covering or embodied by the Network Content, including, without limitation, all copyrights, moral rights, trademark rights and patent rights. The Network Content does not include Developer Content or End-User Content, as described herein. You do not acquire any ownership interest in any Network Content by accessing or using the Network or Network Content. 26 | 27 | The Subject Persons and/or any entities and/or persons who have introduced modifications or proposed modification to the Network or such Network Content may make the applicable source code for such software available for download as open source software. You agree to be bound by the license agreement that applies to any open source software used in the Network or any Network Content. You will not indicate that you are associated with the entities and/or persons who created such software in connection with your use, modifications or alterations of the software. 28 | 29 | ## 3. System Requirements 30 | To access the Network, you will need a compatible device, Internet access, and certain software that may require updates or upgrades. Your ability to use the Network may be affected by the performance of hardware, software, and Internet access. You agree that such system requirements, which may change from time to time, are your responsibility. You are responsible for any costs you incur to access the Internet. 31 | 32 | ## 4. Your Use and End-User Content and Developer Content 33 | You may access, browse and use the Network and Network Content only in accordance with these Terms. You may not copy, reproduce, modify, distribute, transmit, display, perform, publish or otherwise use or exploit, through any means or media, any of the Network or Network Content, except as provided herein. 34 | 35 | Parts of the Network may allow End-Users (and possibly others) to post, upload, transmit or submit content and information to the Network (collectively, “__End-User Content__”), and parts of the Network will allow Developers to create, upload and operate decentralized applications over the Network (collectively, “__Developer Content__”). 36 | 37 | When you upload, post, publish or make available any End-User Content or Developer Content on the Network, you grant any other user of the Network a perpetual, non-exclusive, royalty-free, and worldwide license to publicly display, communicate, distribute, host, publish, reproduce, make modifications or derivative works (solely for the purpose of better showcasing your User Generated Content) store and to use such End-User Content or Developer Content, in connection with the use and operation of the Network. When you upload, post, publish or make available any End-User Content or Developer Content to other users on the Network, you grant to such other users a non-exclusive and royalty-free license, to access and view your End-User Content or Developer Content. Please note that no party on the Network will monitor or control what other users do with your End-User Content or Developer Content. 38 | 39 | Please do not post any confidential, secret or proprietary information or material through the Network. You are entirely responsible for maintaining the confidentiality of your End-User Content or Developer Content and any of your non-public information. It is your responsibility to obtain any and all consents required under any applicable laws, regarding the posting of any personal information of others which is part of the End-User Content or the Developer Content, and to adhere to any applicable laws regarding such information. By providing End-User Content and/or Developer Content, you: (i) represent and warrant, to all other users of the Network, that End-User Content and/or Developer Content is your original creation, that you own or otherwise control all of the rights in End-User Content and/or Developer Content, or that you have the rights necessary to grant the license to End-User Content and/or Developer Content granted herein, and that End-User Content and/or Developer Content does not violate any rights, including rights of privacy, of any party and does not otherwise violate the law; and (ii) shall indemnify and hold harmless any and all Subject Persons from and against any and all claims, actions and damages (including, without limitation, court costs, legal fees, accounting fees and amounts paid in settlement) that are related to or result from the use of the Network, the Network Content, End-User Content and/or Developer Content, and/or your violation of these Terms or your representations and warranties hereunder. You will cooperate as fully as reasonably required in the defense of any such claim or action. 40 | 41 | Developers are responsible for adhering to applicable law regarding any End-User Content acquired as a result of the activities of the application operated by such Developer. 42 | 43 | No party will bear any liability for any loss, damage, cost or expense that you may suffer or incur as a result of or in connection with uploading any Developer Content or End-User Content. You hereby acknowledge and agree that any Developer Content and/or End-User Content is non-confidential. 44 | 45 | You understand and agree that you are solely responsible for your End-User Content and/or Developer Content, and the consequences of sending posting or publishing such End-User Content and/or Developer Content, on the Network, in any way. 46 | 47 | In the event that, in order to serve as a Validator or Guardian, you are required to present certain information for registration purchases, you hereby acknowledge that you are providing the Network with such information on your own free will, for the purpose of becoming eligible to act as a Validator or Guardian on the Network, and that you consent to such information being stored in accordance with the procedures of the Network, and waive any and all claims against the Subject Persons relating to such information. You further acknowledge that since such information may be stored on a public blockchain network, it may be technically impossible for any information to be deleted from such network once submitted. 48 | 49 | NO PARTY OTHER THAN THE PARTY POSTING SUCH USER CONTENT TAKES ANY RESPONSIBILITY OR ASSUMES ANY LIABILITY FOR ANY END-USER CONTENT OR DEVELOPER CONTENT UPLOADED, POSTED, PUBLISHED AND MADE AVAILABLE BY YOU OR ANY OTHER USER ON THE NETWORK, OR FOR ANY LOSS OR DAMAGE THERETO, NOR IS ANY OTHER PARTY LIABLE FOR ANY MISTAKES, DEFAMATION, LIBEL, FALSEHOODS, OBSCENITIES OR PORNOGRAPHY YOU OR ANY OTHER USERS MAY ENCOUNTER. 50 | 51 | ## 5. Governance, Voting and Procedures of the Network 52 | As a decentralized network, the actual existence and performance of the Network is dependent on the collective actions of various participants in the Network, including, among others, Validators, Guardians and Token Holders. The Network may not continue to exist and may not perform as expected if such parties cease their activities on the Network. No one, including the Subject Persons, can guarantee that such parties will continue to act or that the Network will continue exist or perform at the expected level. 53 | 54 | You hereby expressly acknowledge and agree that the Network is governed by defined voting governance guidelines, as such may be in effect and amended from time to time in accordance with the then-applicable governance framework of the Network. 55 | 56 | If you are a Validator, you hereby expressly acknowledge and agree that your activities on the Network are subject to the Validator statement set forth here: [https://], that you will comply with the provisions of such statement in all respects in your activities on the Network and that failure to comply with such provisions may result in penalties in accordance with the then-applicable governance provisions of the Network. 57 | 58 | Without limiting the foregoing, you hereby acknowledge and agree that: (i) only Token Holders who are beneficial owners of Orbs Tokens are permitted to vote or delegate such Orbs Tokens in the course of any governance or decision-making procedure to which such Orbs Tokens have participation rights; (ii) any person holding any Orbs Tokens in the capacity of custodian on behalf of a Token Holder who is not the beneficial owner of such Orbs Tokens shall not have the right to vote, delegate or otherwise participate in the governance of the Network, and shall not take any such action unless expressly instructed to do so by the Token Holder who is the beneficial owner of such Orbs Tokens; (iii) no user shall offer nor accept anything of value in exchange for a vote of any type, except in accordance with any reward system of the Network that may be in effect from time to time, nor shall any user unduly influence the vote of another. 59 | 60 | The Network has been designed to provide service cost stability to users and developers by setting the prices of the computing resources required for each type of on-demand service available on the Orbs networks at a certain number of Orbs tokens, which prices have been set forth on the Orbs Operation Fees document at [https://www.orbs.com/pricing](https://www.orbs.com/pricing). The specific prices listed therein are presented in good faith and believed to be correct at the time of publication, however the model presented may be changed from time to time during the launch period, including as the result of ongoing testing of the model and actual results before and during the launch period. 61 | 62 | The pricing list for computing services on the Orbs network may be subject to change from time to time, including, without limitation, by replacing such prices with prices based on an index of prices published by third party cloud providers or by other methods of pegging transaction costs on the Orbs network to a dedicated amount of computing capacity. 63 | 64 | Without limiting the generality of any of the foregoing, changes to the specific prices listed on the price list may occur at any time during or after the launch period as a result of adjustments to the pricing model based on the outcome of testing, adjustments to the pricing model based on actual results during the launch period, additional experience in the behavior of the market for dedicated capacity, changes to the information available from third party cloud service providers, changes due to unforeseen cost increases or decreased of cloud computing, and changes initiated by participants in the governance of the Orbs network. 65 | 66 | ## 6. Prohibited Conduct 67 | You warrant and agree that, while accessing or using the Network, you will not: 68 | 69 | * access, use or attempt to access or use another user’s account, including any private key, public key or wallet address, that you are not authorized to access or use; 70 | 71 | * interfere with or disrupt the operation of the Network or the servers or networks that host the Network, or disobey any laws, regulations, requirements, procedures, or policies of such servers or networks; 72 | 73 | * engage or attempt to engage in any attack or other malicious behavior or activity that threatens the integrity of the Network, including, without limitation, 51% attacks, double-spend attacks, eclipse attacks, transaction malleability attacks, timejacking, routing attacks, Sybil attacks, denial of service attacks, or race condition attacks; 74 | 75 | * create a false identity for the purpose of misleading others or otherwise impersonate any person or entity or misrepresent your affiliation with any other person or entity, whether actual or fictitious, including anyone from the Network, the licensors of any content hosted on the Network or anyone otherwise affiliated with the Network; 76 | 77 | * transmit or otherwise make available in connection with the Network any virus, worm, Trojan Horse, time bomb, web bug, spyware, or any other computer code, file, or program that may or is intended to damage or hijack the operation of any hardware, software, or telecommunications equipment, or any other actually or potentially harmful, disruptive, or invasive code or component; 78 | 79 | * obtain or attempt to gain unauthorized access to other computer systems, materials, information or any Network Content available on or through the Network through any means, including through means not intentionally made publicly available or provided through the Network; 80 | 81 | * engage in any unauthorized means of accessing, logging-in or registering on the Network, or obtaining lists of users or other information from or through the Network, including, without limitation, any information residing on any server or database connected to the Network; 82 | 83 | * use the Network or Network Content in any manner that could interrupt, damage, disable, overburden or impair the Network, or interfere with any other party’s use of the Network, including, without limitation, sending mass unsolicited transactions or “flooding” servers; 84 | 85 | * use the Network or Network Content in violation of proprietary or legal rights or rights of any party; 86 | 87 | * use the Network or Network Content in violation of any applicable law; 88 | 89 | * use the Network or Network Content to publish, post, send, upload, submit, display or disseminate any information or material and/or otherwise make available or engage in any conduct that is libelous, defamatory, abusive, threatening, harmful, offensive, obscene, tortious or otherwise objectionable; or 90 | 91 | * attempt (or encourage or support anyone else’s attempt) to disable, bypass, modify, defeat, circumvent, reverse-engineer, decrypt, or otherwise alter, or interfere with, the Network or the Network Content, including without limitation any security, digital rights management or data encryption components limiting access to Network Content; 92 | 93 | ## 7. Purchases 94 | You acknowledge that entering into any transaction electronically (including without limitation all records relating to such transactions) constitutes your agreement and intent to be bound by and to pay for such agreements and transactions. Such transactions may, among other things, include payments between participants for their activities on the network, transaction fees paid by Developers to Validators for providing computing resources on the network, arrangements between Guardians and Token Holders with respect to staking, voting and rewards within the Network’s security, governance and operation mode and arrangements with respect to fees paid by End Users to Developers. Notwithstanding that such transactions and other similar transactions may be allowed, facilitated or encouraged by the design of the Network and components included in the Network Content, you acknowledge and agree that the actual entry into any such agreement, transaction or arrangement by any users of the Network is accomplished as a peer-to-peer transaction between the parties thereto and is subject to the terms of the agreement between such parties. You are solely responsible for any disputes you may have with any Network participant or any other party regarding such agreements and transactions. THE SUBJECT PERSONS DISCLAIM ALL LIABILITY RELATED TO ANY DISPUTES BETWEEN, BY AND AMONG YOU AND ANY DEVELOPERS, END-USERS, GUARDIANS, TOKEN HOLDERS AND/OR VALIDATORS. 95 | 96 | ## 8. Objectionable Content 97 | You may find some Network Content, Developer Content and/or End-User Content offensive or objectionable. You agree that your use of the Network, including access to such Network Content, Developer Content and/or End-User Content, is at your sole risk, and that the Subject Persons shall have no liability to you for content that may be found to be offensive or objectionable. Descriptions of Network Content, Developer Content and End-User Content available on the Network are for your convenience. 98 | 99 | ## 9. Links to Third-Party Websites 100 | The Network may include links to websites of third parties. If you click on these links, you will leave the Network. Network participants are not responsible for their content or operation. You should exercise your own judgment in evaluating and using these websites. When you link to these websites, you become subject to their terms and conditions of use and privacy policies. 101 | 102 | ## 10. Notifications concerning Blockchain Technology and Virtual Currency 103 | The Network is based on blockchain technology. Furthermore, the Network requires the use of a virtual currency, the Orbs Tokens, for certain aspects of its functionality. Without limitation, the Orbs Tokens are required for Developers to pay transaction fees to Validators for providing the services needed to run their applications on the Network. In addition, participants in the Network’s security, governance and operations model, including Guardians and Token Holders, may utilize the Orbs Tokens in order to participate in the model by direct voting or delegating the vote associated with such Orbs Tokens, and may receive rewards in the form of Orbs Tokens for such activities, all in accordance with the then-applicable security governance and operations model. 104 | 105 | Accordingly, when using this Network, you should be aware of the following risks associated with virtual currency, including the Orbs Tokens, and blockchain-based software, including the Network: 106 | 107 | * virtual currency is not legal tender, is not backed by the government, and accounts and value balances are not subject to Federal Deposit Insurance Corporation or Securities Investor Protection Corporation protections or similar laws in any jurisdiction; 108 | 109 | * legislative and regulatory changes or actions at the state, federal, or international level may adversely affect the use, transfer, exchange, and value of virtual currency; 110 | 111 | * transactions in virtual currency are generally irreversible, and, accordingly, losses due to fraudulent or accidental transactions may not be recoverable; 112 | 113 | * some virtual currency transactions shall be deemed to be made when recorded on a “block chain” ledger, which is not necessarily the date or time that the customer initiates the transaction; 114 | 115 | * the value of virtual currency is derived from the continued willingness of market participants to exchange fiat currency for virtual currency, which may result in the potential for permanent and total loss of value of a particular virtual currency should the market for that virtual currency disappear; 116 | 117 | * there is no assurance that a person who accepts a virtual currency as payment today will continue to do so in the future; 118 | 119 | * the volatility and unpredictability of the price of virtual currency relative to fiat currency may result in significant loss or tax liability over a short period of time; 120 | 121 | * the nature of virtual currency may lead to an increased risk of fraud or cyber-attack; 122 | 123 | * the nature of virtual currency means that any technological difficulties experienced by You may prevent the access or use of a customer’s virtual currency; 124 | 125 | * the Network is likely to experience scheduled and unscheduled downtime, interruptions, delays, hard forks, bugs, viruses, and cyberattacks; 126 | 127 | * the Network may from time to time lack features or functionality and/or require maintenance, support or other adjustments; 128 | 129 | * the Network rests or relies on open-source software, and there is a risk that a person introduces weaknesses, bugs, viruses or other malicious code into the core infrastructural elements of the Network causing the system to lose or erase all or a portion of the Orbs Tokens used in connection with the Network; 130 | 131 | * it is possible that the Network will not be used by a large number of external businesses, individuals, and other organizations and that there will be limited public interest in the creation and development of distributed applications. Such a lack of interest could impact the development of the Network and potential uses of Orbs Tokens. It is not possible to predict the success of any development efforts of any party; 132 | 133 | * the actual existence and performance of the Network is dependent on the collective actions of various participants in the Network, including, among others, Validators, Guardians and Token Holders. It is possible that the Network may not continue to exist and may not perform as expected if such parties cease their activities on the Network. No one, including the Subject Persons, can guarantee that such parties will continue to act or that the Network will continue exist or perform at the expected level; 134 | 135 | * you recognize that the Network is under development and may undergo significant changes over time and you acknowledge that any expectations regarding the form and functionality of the Network held by you may not be met upon release of the Network or any update thereto, for any number of reasons including a change in the design and implementation plans and execution of the implementation of the Network; 136 | 137 | * the state of cryptocurrency can advance over time and advances in code cracking, or technical advances such as the development of quantum computers, could present risks to the Orbs Tokens and the Network, which could result in the theft or loss of Orbs Tokens. To the extent possible, participants in the Network may attempt to update the protocol underlying the Network to account for any advances in cryptography and to incorporate additional security measures, but the future of cryptography cannot be predicted and there can be no guarantee that any security updates will be made in a timely or successful manner; 138 | 139 | * as with other cryptocurrencies, the blockchain used for the Network is susceptible to mining attacks, including but not limited to double-spend attacks, majority mining power attacks, “Selfish-mining” attacks or race condition attacks and any successful attacks present a risk to the Network, expected proper execution and sequencing of transactions in Orbs Tokens, and expected proper execution and sequencing of contract computations. Despite the efforts of participants in the Network, including Validators and Guardians, known or novel mining attacks may be successful. 140 | 141 | * if the Network is rapidly adopted, the demand for Orbs Tokens could rise dramatically and at a pace that exceeds the rate with which new Orbs Tokens are released from reserves or otherwise become available for use. Under such a scenario, the entire Network could become destabilized, due to the increased cost of running distributed applications. In turn, this could dampen interest in the Network and Orbs Tokens. Instability in the demand for Orbs Tokens may lead to a negative change of the economical parameters of an Orbs Token-based business which could result in the business being unable to continue to operate economically or to cease operation. 142 | 143 | * if the Network is rapidly adopted, the demand for transaction processing and distributed application computations could rise dramatically and at a pace that exceeds the rate with which Validators can bring online additional computing power. Under such a scenario, the entire Network could become destabilized, due to the increased cost of running distributed applications. In turn, this could dampen interest in the Network and the Orbs Tokens. Insufficiency of computational resources and an associated rise in the price of Orbs Tokens could result in businesses being unable to acquire scarce computational resources to run their applications. 144 | 145 | * It is possible that alternative which utilize the same open-source source code and open source protocol underlying the Network could be established. The Network may compete with these alternative networks, which could potentially negatively impact the Network and the Orbs Tokens; and 146 | 147 | * the Network could be impacted in whole or in part by one or more regulatory or governmental inquiries or actions, which could impede, limit or restrict the use or transfer of Orbs Tokens or otherwise result in the complete or partial loss in value of Orbs Tokens. 148 | 149 | You hereby expressly acknowledge and agree that (i) you are accepting and using the Network and the Orbs tokens at your sole risk and expense; (ii) you have an adequate understanding of the risks, usage and intricacies of cryptographic tokens such as the Orbs tokens and blockchain-based software such as the Network, including the risks set forth above; (iii) any and all Subject Persons shall have no responsibility or liability for the loss, transfer, misappropriation, theft, use or misuse of any Orbs Tokens, including as utilized in connection with the Network, or any financial or physical harm or loss related thereto, and you hereby irrevocably waive any and all rights and claims with respect thereto and claims with respect thereto, (iv) you will comply with any and all applicable rules and laws regarding your use of Orbs Tokens, including in connection with the Network and (vi) the Subject Persons not endorse or recommend the use of any software or hardware wallet services and/or market exchanges (including any over-the-counter market) in connection with any storage, transfer or other transaction related to Orbs Tokens, all of which may be used at your sole risk and expense. 150 | 151 | ## 11. Representations and Warranties and Warranty Disclaimers 152 | The Network is a peer-to-peer platform with a decentralized, blockchain-based architecture designed to provide blockchain infrastructure-as-a-service. As a decentralized platform, the actual existence and performance of the Network is dependent on the collective actions of various participants in the Network, including Validators, Guardians and Token Holders. No party, including the Subject Persons, can exert full control over the operation of the Network or the actual results obtained from its use. You acknowledge and agree that the control of the Network is distributed and that accordingly no particular party, including the Subject Persons, is able to provide warranties or guarantees regarding the future operations or actual results of any activity on the Network. 153 | 154 | Developers specifically agree that they will not bring any legal actions against any Validator or Guardian operator based on such Validator or Guardian operator’s conduct as a Validator or Guardian, as applicable, and that they will indemnify all Validator and Guardian operators from and against any and all claims brought by the Developer’s End-Users. 155 | 156 | All Validator and Guardian operators and Developers agree that they will not bring any legal actions against the Subject Persons. 157 | 158 | The Network is accessible world-wide. The Network and Network Content may not be appropriate or authorized for use in all countries, states, provinces, counties or any other jurisdictions. Your access and use of the Network may not be legal in your jurisdiction. If you choose to access, browse or use the Network, you do so on your own initiative and risk, and you are responsible for compliance with all applicable laws if, and to the full extent that, such laws and restrictions are applicable. Any offer for any feature or function made on the Network is void where prohibited. 159 | 160 | Any information provided on the Network is of a general nature only and cannot create liability concerning any action that any person may take based on any information or guidance provided at the Network. 161 | 162 | Some Network Content may be provided by the users of the Network. The Subject Persons do not obtain or control any rights in, and do not exert editorial control over, such Network Content. They do not independently verify the representations and warranties made by the users with respect to such Network Content. 163 | 164 | The Subject Persons do not guarantee the accuracy, timeliness, correctness, completeness, performance or fitness for a particular purpose of the Network or any of Network Content, End-User Content and/or Developer Content. They are not liable for any errors, omissions, or inaccurate Network Content, End-User Content and/or Developer Content. Furthermore, the Subject Persons disclaim: (a) any and all responsibility or liability for the accuracy, content, completeness, legality, reliability, or availability or operability of information or materials displayed on the Services, or the Company website or any of its subpages; (b) any and all responsibility for the conduct of any user of the Services; (c) any and all responsibility for any harm resulting from downloading or accessing any information or material on the Internet through the Service, the Company website or any of its subpages; (d) any and all responsibility for any financial gains, losses or tax consequences associated with the your use of the Services and the associated cryptocurrency. 165 | 166 | THE NETWORK AND ITS CONTENT ARE PROVIDED “AS IS” AND “AS AVAILABLE” WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY FOR INFORMATION, DATA, DATA PROCESSING SERVICES, UPTIME OR UNINTERRUPTED ACCESS, ANY WARRANTIES CONCERNING THE AVAILABILITY, ACCURACY OR USEFULNESS OF THE NETWORK AND ITS CONTENT AND ANY IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR NON-INFRINGEMENT, WHICH ARE EXCLUDED FROM THESE TERMS TO THE EXTENT THAT THEY MAY BE EXCLUDED AS A MATTER OF LAW. NO PARTY WARRANTS THAT THE NETWORK OR ITS CONTENT WILL BE TIMELY, SECURE, UNINTERRUPTED, OR OPERATED FREE OF DELAYS IN TRANSMISSION, FAILURE IN PERFORMANCE, COMPUTER VIRUSES, INACCURACIES, ERRORS, OR DEFECTS. YOU USE THE NETWORK AT YOUR OWN RISK. YOU ARE SOLELY RESPONSIBLE FOR IMPLEMENTING SUFFICIENT PROCEDURES AND VIRUS CHECKS (INCLUDING ANTI-VIRUS AND OTHER SECURITY CHECKS) TO SATISFY YOUR PARTICULAR REQUIREMENTS FOR THE ACCURACY AND SECURITY OF DATA INPUT AND OUTPUT. THERE IS NO WARRANTY THAT THE NETWORK WILL MEET USERS’ OR DEVELOPER’S REQUIREMENTS. NO ADVICE, RESULTS OR INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY YOU THROUGH THE NETWORK SHALL CREATE ANY WARRANTY NOT EXPRESSLY MADE HEREIN. 167 | 168 | Some jurisdictions do not allow the disclaimer of implied warranties, so the foregoing disclaimers may not apply to you. 169 | 170 | YOU ACKNOWLEDGE AND AGREE THAT YOUR SOLE REMEDY FOR ANY PROBLEMS OR DISSATISFACTION WITH THE NETWORK IS TO DISCONTINUE ALL USE OF THE NETWORK. 171 | 172 | ## 12. Limitation of Liability 173 | EXCEPT AS SET FORTH HEREIN, UNDER NO CIRCUMSTANCES, INCLUDING, WITHOUT LIMITATION, BREACH OF CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY OR ARISING UNDER ANY OTHER LEGAL OR EQUITABLE THEORY WILL THE SUBJECT PERSONS BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING, BUT NOT LIMITED TO, DIRECT, INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL DAMAGES THAT ARISE OUT OF OR IN CONNECTION WITH THE USE OF THE NETWORK OR THE ORBS TOKENS OR WITH THE DELAY OR INABILITY TO USE THE NETWORK, THE ORBS TOKENS OR NETWORK CONTENT, OR FOR ANY INFORMATION, SOFTWARE APPLICATIONS, PRODUCTS OR SERVICES OBTAINED THROUGH THE NETWORK, OR FROM THE FAILURE OF THE NETWORK TO PERFORM AS DESCRIBED OR EXPECTED, OR FROM THE FAILURE OF THE SUBJECT PARTIES TO PERFORM UNDER THESE TERMS OR OTHERWISE ARISING OUT OF THE USE OF THE NETWORK, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THOSE ASPECTS OF THE HEREIN LIMITATION MAY NOT APPLY TO YOU, IN WHICH CASE LIABILITY SHALL BE LIMITED TO THE FULLEST EXTENT PERMITTED BY LAW. 174 | 175 | IN NO EVENT SHALL THE SUBJECT PERSONS BE LIABLE FOR, OR IN CONNECTION WITH, ANY CONTENT POSTED, TRANSMITTED, EXCHANGED OR RECEIVED BY OR ON BEHALF OF ANY USER OR OTHER PERSON ON OR THROUGH THE NETWORK (INCLUDING, WITHOUT LIMITATION, ANY OF YOUR END-USER CONTENT AND/OR DEVELOPER CONTENT). IN NO EVENT SHALL SUCH ENTITIES’ OR PERSONS’ TOTAL LIABILITY TO YOU FOR ALL DAMAGES, LOSSES AND CAUSES OF ACTION EXCEED, IN THE AGGREGATE, ONE HUNDRED U.S. DOLLARS (US$100). 176 | 177 | ## 13. Indemnification 178 | You agree to hold harmless and indemnify the Subject Persons from and against any action, cause claim, suit, judgment, damage (actual and consequential), debt, demand, expense or liability (including reasonable costs and attorney’s fees) of every kind and nature, asserted by any person, arising from or in any way related to your use of the Network or the Orbs Tokens. 179 | 180 | ## 14. No Relationship 181 | There is no agency, partnership, joint venture, employee-employer or franchisor-franchisee relationship between you and the Subject Persons or between them and any other user of the Network. You acknowledge that by submitting End-User Content or Developer Content, no confidential, fiduciary, contractually implied or other relationship is created between you and the Subject Persons other than pursuant to these Terms. 182 | 183 | ## 15. Taxes 184 | You hereby acknowledge and agree that you are responsible for all tax consequences of any transaction or activity you undertake on the Network, any provision or receipt of the Services, and/or any reward or other value received in connection therewith. You are solely responsible for determining whether or not to use the Network or to receive or provide any Services and you acknowledge that the Services may be subject to export restrictions and economic sanctions imposed by law. To the extent that the Subject Persons is a party to any transaction on the Network, you acknowledge and agree that the Subject Persons may withhold any tax or other amounts required by applicable law from any payment or consideration payable as a result of such transaction. You agree to indemnify and hold harmless the Subject Persons, or any of them, from any taxes imposed against the Subject Persons as a result of your activities on the Network, any loss, liability or cost which such Subject Persons determines will or has been incurred as a result of any taxes resulting from your activities on the Network, or any proceeding brought against the Subject Parties by any governmental authority in connection with any taxes resulting from your activities on the Network. 185 | 186 | ## 16. Assignment 187 | Your agreement to these Terms is personal to you and you may not transfer or assign it to any third party. 188 | 189 | ## 17. Entire Agreement 190 | YOU ACKNOWLEDGE THAT YOU HAVE READ THIS AGREEMENT, UNDERSTAND IT, AND AGREE TO BE BOUND BY ITS TERMS AND CONDITIONS. 191 | 192 | These Terms shall be deemed to include all other notices, policies, disclaimers and other terms and conditions contained in the Network and Network Content. These Terms constitute the entire agreement among the Network participants and supersede all prior or contemporaneous communications and proposals, whether electronic, oral or written, between you and other Network participants, with respect to your use of the Network and all matters relating to your access to, and/or use of, the Network and Network Content. A printed version of these Terms and of any notice given in electronic form shall be admissible in any and all judicial or administrative proceedings based upon or relating to these Terms to the same extent as other business documents and records originally generated and maintained in printed form. 193 | 194 | These Terms are subject to change from time to time in accordance with the then-applicable governance procedures of the Network. 195 | 196 | Any dispute to which the Subject Persons are a party arising out of or related to the Network will be brought in, and you hereby consent to exclusive jurisdiction and venue of, the competent courts of the Tel-Aviv-Jaffa District, Israel, provided, however, that nothing herein shall be deemed to preclude the Subject Persons from bringing any suit, enforcing any right or taking other legal action in your local jurisdiction. You agree to waive all defenses of lack of personal jurisdiction and forum non-convenience and agree that process may be served in a manner authorized by applicable law or court rule. 197 | 198 | If any part of these Terms is determined to be invalid or unenforceable under applicable law including, without limitation, the warranty disclaimers and liability limitations stated herein, then the invalid or unenforceable provision(s) will be deemed superseded by a valid, enforceable provision that most closely matches the intent of the original provision, and the remainder of these Terms shall continue in full effect. 199 | 200 | As part of these Terms, all Developers and any other participant who facilitates the use of the Network, directly or indirectly, by any End User, shall undertake to ensure that such End-User enters into an agreement or other arrangement which governs the relationship between the Developer or other participant and such the End User regarding the Network and obligates such End-User to be subject to these Terms. Such Developer or other participant is solely responsible for the effectiveness of such arrangement with the applicable End Users. 201 | 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Orbs Client SDK JavaScript 2 | 3 | > Client SDK for the Orbs blockchain in JavaScript and TypeScript for Node.js and browsers 4 | 5 | This page describes SDK API `v2.0.0`, for upgrade from `v1.x` please [follow the instructions](https://github.com/orbs-network/orbs-client-sdk-javascript/pull/21). 6 | 7 | ## Installation 8 | 9 | ### Node.js 10 | 11 | 1. Install the NPM package: 12 | 13 | ```sh 14 | npm install orbs-client-sdk 15 | ``` 16 | 17 | 2. Import the client in your project 18 | 19 | ```js 20 | const Orbs = require("orbs-client-sdk"); 21 | ``` 22 | 23 | ### Browser 24 | 25 | 1. Install via NPM package: 26 | 27 | 28 | ```sh 29 | npm install orbs-client-sdk 30 | ``` 31 | 32 | 2. Import the client in your project 33 | 34 | ```js 35 | import { createAccount, Client } from 'orbs-client-sdk' 36 | ``` 37 | 38 | ## Usage 39 | 40 | 1. Create a few end user accounts: 41 | 42 | ```js 43 | const Orbs = require("orbs-client-sdk"); 44 | const sender = Orbs.createAccount(); 45 | const receiver = Orbs.createAccount(); 46 | ``` 47 | 48 | 2. Create a client instance: 49 | 50 | ```js 51 | const virtualChainId = 42; 52 | const client = new Orbs.Client("http://node-endpoint.com", virtualChainId, "TEST_NET", new Orbs.LocalSigner(sender)); 53 | ``` 54 | 55 | 3. Send a transaction: 56 | 57 | ```js 58 | const [tx, txId] = await client.createTransaction( "BenchmarkToken", "transfer", [Orbs.argUint64(10), Orbs.argAddress(receiver.address)]); 59 | const response = await client.sendTransaction(tx); 60 | ``` 61 | 62 | 4. Check the transaction status: 63 | 64 | ```js 65 | const response = await client.getTransactionStatus(txId); 66 | ``` 67 | 68 | 5. Deploy a smart contract: 69 | 70 | ```js 71 | // Load the content of the contract file(s) that we want to deploy 72 | // NOTE : These two file are part of the same contract. 73 | const sources = [ 74 | readFileSync(`${__dirname}/../contract/increment_base.go`), 75 | readFileSync(`${__dirname}/../contract/increment_functions.go`) 76 | ]; 77 | 78 | // Build The deployment query 79 | // Notice that in this case the contract's name will be "Inc" 80 | const [deploymentTx, deploymentTxId] = await client.createDeployTransaction("Inc", Orbs.PROCESSOR_TYPE_NATIVE, ...sources); 81 | 82 | // Execute the deployment query 83 | const deploymentResponse = await client.sendTransaction(deploymentTx); 84 | ``` 85 | 86 | 6. Call a smart contract method: 87 | 88 | ```js 89 | const query = await client.createQuery("BenchmarkToken", "getBalance", [Orbs.argAddress(receiver.address)]); 90 | const response = await client.sendQuery(query); 91 | ``` 92 | 93 | ## Test 94 | 95 | 1. After running `npm install` locally, make sure folder `./contract` is created. It's needed for the contract test and cloned from the [reference implementation](https://github.com/orbs-network/orbs-client-sdk-go). The codec contract test encodes and signs all message types and compares to a [JSON file](https://github.com/orbs-network/orbs-client-sdk-go/tree/master/test/codec) containing the official result required to be compatible to the Orbs protocol specifications. 96 | 97 | 2. Build the library with `npm run build` 98 | 99 | 3. To run the end-to-end test, install [`gamma-cli`](https://github.com/orbs-network/gamma-cli) 100 | 101 | 4. Run all tests (unit and e2e) with `npm run test` 102 | -------------------------------------------------------------------------------- /e2e/browser/browser.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | const GammaDriver = require("../gamma-driver"); 10 | const httpServer = require("http-server"); 11 | 12 | const VIRTUAL_CHAIN_ID = 42; // gamma-cli config default 13 | const STATICS_PORT = 8081; 14 | 15 | const clickOnElement = async selector => await page.click(`${selector}`); 16 | const getElementText = async selector => await page.$eval(`${selector}`, el => el.innerText); 17 | const clearInputText = async selector => { 18 | await page.focus(selector); 19 | await page.$eval(selector, el => el.setSelectionRange(0, el.value.length)); 20 | await page.keyboard.press("Backspace"); 21 | }; 22 | const setInputText = async (selector, value) => { 23 | await clearInputText(selector); 24 | await page.focus(selector); 25 | await page.keyboard.type(value); 26 | }; 27 | 28 | const fillServerDetails = async (endpoint, virtualChainId) => { 29 | await setInputText("#virtual-chain-id", virtualChainId.toString()); 30 | await setInputText("#endpoint", endpoint); 31 | }; 32 | 33 | const startStaticsServer = (port, proxy) => { 34 | return new Promise(resolve => { 35 | const server = httpServer.createServer({ proxy }); 36 | server.listen(port, "localhost", () => resolve(server)); 37 | }); 38 | }; 39 | 40 | describe("E2E browser", () => { 41 | const gammeDriver = new GammaDriver(); 42 | let staticsServer; 43 | 44 | beforeAll(async () => { 45 | jest.setTimeout(60000); 46 | await gammeDriver.start(); 47 | const gammaEndpoint = gammeDriver.getEndpoint(); 48 | console.log("gammaEndpoint", gammaEndpoint); 49 | staticsServer = await startStaticsServer(STATICS_PORT, gammaEndpoint); 50 | const staticsServerUrl = `http://localhost:${STATICS_PORT}`; 51 | await page.goto(`${staticsServerUrl}/e2e/browser/`); 52 | await fillServerDetails(staticsServerUrl, VIRTUAL_CHAIN_ID); 53 | }); 54 | 55 | afterAll(async () => { 56 | staticsServer.close(); 57 | await gammeDriver.stop(); 58 | }); 59 | 60 | it("should create the sender account", async () => { 61 | await clickOnElement("#create-sender-account"); 62 | const senderAccountId = await getElementText("#sender-account-id"); 63 | const accountIdLength = senderAccountId.split(",").length; 64 | expect(accountIdLength).toEqual(32); 65 | }); 66 | 67 | it("should create Orbs.Client instance", async () => { 68 | await clickOnElement("#create-orbs-client"); 69 | const orbsClientResult = await getElementText("#orbs-client-result"); 70 | expect(orbsClientResult).toEqual("Created"); 71 | }); 72 | 73 | it("should create the receiver account", async () => { 74 | await clickOnElement("#create-receiver-account"); 75 | const receiverAccountId = await getElementText("#receiver-account-id"); 76 | const accountIdLength = receiverAccountId.split(",").length; 77 | expect(accountIdLength).toEqual(32); 78 | }); 79 | 80 | it("should create a transaction", async () => { 81 | await clickOnElement("#create-tx"); 82 | const txId = await getElementText("#tx-id"); 83 | expect(txId.length).toEqual(82); 84 | }); 85 | 86 | it("should send the transaction", async () => { 87 | await clickOnElement("#send-tx"); 88 | await expect(page).toMatchElement("#transfer-response-request-status", { text: "COMPLETED" }); 89 | await expect(page).toMatchElement("#transfer-response-execution-result", { text: "SUCCESS" }); 90 | await expect(page).toMatchElement("#transfer-response-transaction-status", { text: "COMMITTED" }); 91 | }); 92 | 93 | it("should verify the transaction status", async () => { 94 | await clickOnElement("#get-tx-status"); 95 | await expect(page).toMatchElement("#status-response-request-status", { text: "COMPLETED" }); 96 | await expect(page).toMatchElement("#status-response-execution-result", { text: "SUCCESS" }); 97 | await expect(page).toMatchElement("#status-response-transaction-status", { text: "COMMITTED" }); 98 | }); 99 | 100 | it("should verify the transaction receipt proof", async () => { 101 | await clickOnElement("#get-tx-receipt-proof"); 102 | await expect(page).toMatchElement("#proof-response-request-status", { text: "COMPLETED" }); 103 | await expect(page).toMatchElement("#proof-response-execution-result", { text: "SUCCESS" }); 104 | await expect(page).toMatchElement("#proof-response-transaction-status", { text: "COMMITTED" }); 105 | const packedProofByteLength = await getElementText("#proof-response-packedproof-bytelength"); 106 | const packedReceiptByteLength = await getElementText("#proof-response-packedreceipt-bytelength"); 107 | expect(parseInt(packedProofByteLength)).toBeGreaterThan(20); 108 | expect(parseInt(packedReceiptByteLength)).toBeGreaterThan(20); 109 | }); 110 | 111 | it("should send a query", async () => { 112 | await clickOnElement("#send-query"); 113 | await expect(page).toMatchElement("#balance-response-request-status", { text: "COMPLETED" }); 114 | await expect(page).toMatchElement("#balance-response-execution-result", { text: "SUCCESS" }); 115 | await expect(page).toMatchElement("#balance-response-value", { text: "10" }); 116 | // await page.waitFor(200000); 117 | }); 118 | }); 119 | -------------------------------------------------------------------------------- /e2e/browser/index.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 26 | 27 | 89 | 90 | 91 |
92 |
93 |
94 |
95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 132 | 133 | 134 | 135 | 136 | 141 | 142 | 143 | 144 | 145 | 152 | 153 | 154 | 155 | 156 | 161 | 162 | 163 |
StepActionResult
1
2
3
4
5 128 |
Transfer Response request status:
129 |
Transfer Response execution result:
130 |
Transfer Response transaction status:
131 |
6 137 |
Status Response request status:
138 |
Status Response execution result:
139 |
Status Response transaction status:
140 |
7 146 |
Proof Response request status:
147 |
Proof Response execution result:
148 |
Proof Response transaction status:
149 |
Proof Response packed proof byteLength:
150 |
Proof Response packed receipt byteLength:
151 |
8 157 |
Balance Response request status:
158 |
Balance Response execution result:
159 |
Balance Response value:
160 |
164 | 165 | 166 | -------------------------------------------------------------------------------- /e2e/contract/increment_base.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/orbs-network/orbs-contract-sdk/go/sdk/v1" 5 | ) 6 | 7 | var PUBLIC = sdk.Export(inc, value) 8 | var SYSTEM = sdk.Export(_init) 9 | 10 | var COUNTER_KEY = []byte("counter") 11 | 12 | func _init() { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /e2e/contract/increment_functions.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/orbs-network/orbs-contract-sdk/go/sdk/v1/state" 4 | 5 | func inc() uint64 { 6 | v := value() + 1 7 | state.WriteUint64(COUNTER_KEY, v) 8 | return v 9 | } 10 | 11 | func value() uint64 { 12 | return state.ReadUint64(COUNTER_KEY) 13 | } 14 | -------------------------------------------------------------------------------- /e2e/contract/increment_functions_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/orbs-network/orbs-contract-sdk/go/testing/unit" 5 | "github.com/stretchr/testify/require" 6 | "testing" 7 | ) 8 | 9 | func TestInc(t *testing.T) { 10 | unit.InServiceScope(nil, nil, func(mockery unit.Mockery) { 11 | inc() 12 | require.EqualValues(t, 1, value()) 13 | }) 14 | } -------------------------------------------------------------------------------- /e2e/gamma-driver.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | const util = require("util"); 10 | const execFile = util.promisify(require("child_process").execFile); 11 | 12 | const GAMMA_PORT = 8080; 13 | const GAMMA_SERVER = "localhost"; 14 | 15 | class GammaDriver { 16 | constructor(server = GAMMA_SERVER, port = GAMMA_PORT, experimental = true) { 17 | this.server = server; 18 | this.port = port; 19 | this.experimental = experimental; 20 | } 21 | 22 | async start() { 23 | try { 24 | const { stdout, stderr } = await execFile("gamma-cli", ["start-local", "-wait", "-env", "experimental", "-port", this.port]); 25 | console.log(stdout); 26 | if (stderr) { 27 | console.error(stderr); 28 | } 29 | } catch (e) { 30 | console.error("Unable to run start gamma-cli"); 31 | } 32 | } 33 | 34 | async stop() { 35 | try { 36 | const { stdout, stderr } = await execFile("gamma-cli", ["stop-local", "experimental", "-port", this.port]); 37 | console.log(stdout); 38 | if (stderr) { 39 | console.error(stderr); 40 | } 41 | } catch (e) { 42 | console.error("Unable to run stop gamma-cli"); 43 | } 44 | } 45 | 46 | getEndpoint() { 47 | return `http://${this.server}:${this.port}`; 48 | } 49 | } 50 | 51 | module.exports = GammaDriver; 52 | -------------------------------------------------------------------------------- /e2e/nodejs/e2e.test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | const Orbs = require("../../dist/orbs-client-sdk.js"); 10 | const GammaDriver = require("../gamma-driver"); 11 | const { readFileSync } = require("fs"); 12 | 13 | const VIRTUAL_CHAIN_ID = 42; // gamma-cli config default 14 | describe("E2E nodejs", () => { 15 | const gammeDriver = new GammaDriver(); 16 | 17 | beforeEach(async () => { 18 | jest.setTimeout(60000); 19 | await gammeDriver.start(); 20 | }); 21 | 22 | afterEach(async () => { 23 | await gammeDriver.stop(); 24 | }); 25 | 26 | test("SimpleTransfer", async () => { 27 | // create sender account 28 | const sender = Orbs.createAccount(); 29 | 30 | // create receiver account 31 | const receiver = Orbs.createAccount(); 32 | 33 | // create client 34 | const endpoint = gammeDriver.getEndpoint(); 35 | const senderClient = new Orbs.Client(endpoint, VIRTUAL_CHAIN_ID, "TEST_NET", new Orbs.LocalSigner(sender)); 36 | 37 | // create transfer transaction 38 | const [tx, txId] = await senderClient.createTransaction("BenchmarkToken", "transfer", [Orbs.argUint64(10), Orbs.argAddress(receiver.address)]); 39 | 40 | // send the transaction 41 | const transferResponse = await senderClient.sendTransaction(tx); 42 | console.log("Transfer response:"); 43 | console.log(transferResponse); 44 | expect(transferResponse.requestStatus).toEqual("COMPLETED"); 45 | expect(transferResponse.executionResult).toEqual("SUCCESS"); 46 | expect(transferResponse.transactionStatus).toEqual("COMMITTED"); 47 | 48 | // check the transaction status 49 | const statusResponse = await senderClient.getTransactionStatus(txId); 50 | console.log("Status response:"); 51 | console.log(statusResponse); 52 | expect(statusResponse.requestStatus).toEqual("COMPLETED"); 53 | expect(statusResponse.executionResult).toEqual("SUCCESS"); 54 | expect(statusResponse.transactionStatus).toEqual("COMMITTED"); 55 | 56 | // check the transaction receipt proof 57 | const txProofResponse = await senderClient.getTransactionReceiptProof(txId); 58 | console.log("Receipt proof response:"); 59 | console.log(txProofResponse); 60 | expect(txProofResponse.requestStatus).toEqual("COMPLETED"); 61 | expect(txProofResponse.executionResult).toEqual("SUCCESS"); 62 | expect(txProofResponse.transactionStatus).toEqual("COMMITTED"); 63 | expect(txProofResponse.packedProof.byteLength).toBeGreaterThan(20); 64 | expect(txProofResponse.packedReceipt.byteLength).toBeGreaterThan(10); 65 | 66 | // create balance query 67 | const query = await senderClient.createQuery("BenchmarkToken", "getBalance", [Orbs.argAddress(receiver.address)]); 68 | 69 | // send the query 70 | const balanceResponse = await senderClient.sendQuery(query); 71 | console.log("Query response:"); 72 | console.log(balanceResponse); 73 | expect(balanceResponse.requestStatus).toEqual("COMPLETED"); 74 | expect(balanceResponse.executionResult).toEqual("SUCCESS"); 75 | expect(balanceResponse.outputArguments[0]).toEqual(Orbs.argUint64(10)); 76 | 77 | // get the block which contains the transfer transaction 78 | const blockResponse = await senderClient.getBlock(transferResponse.blockHeight); 79 | expect(blockResponse.blockHeight).toEqual(transferResponse.blockHeight); 80 | expect(blockResponse.transactionsBlockHeader.blockHeight).toEqual(transferResponse.blockHeight); 81 | expect(blockResponse.transactionsBlockHeader.numTransactions).toEqual(1); 82 | expect(blockResponse.resultsBlockHeader.blockHeight).toEqual(transferResponse.blockHeight); 83 | expect(Orbs.bytesToAddress(blockResponse.resultsBlockHeader.transactionsBlockHash)).toEqual(Orbs.bytesToAddress(blockResponse.transactionsBlockHash)); 84 | expect(blockResponse.resultsBlockHeader.numTransactionReceipts).toEqual(1); 85 | expect(blockResponse.transactions[0].contractName).toEqual("BenchmarkToken"); 86 | expect(blockResponse.transactions[0].methodName).toEqual("transfer"); 87 | expect(blockResponse.transactions[0].inputArguments[0]).toEqual(Orbs.argUint64(10)); 88 | expect(Orbs.bytesToAddress(blockResponse.transactions[0].inputArguments[1].value)).toEqual(receiver.address); 89 | }); 90 | 91 | test("TextualError", async () => { 92 | // create client 93 | const endpoint = gammeDriver.getEndpoint(); 94 | const client = new Orbs.Client(endpoint, VIRTUAL_CHAIN_ID, "TEST_NET", new Orbs.LocalSigner(Orbs.createAccount())); 95 | 96 | // send a corrupt transaction 97 | let error; 98 | try { 99 | const transferResponse = await client.sendTransaction(new Uint8Array([0x01, 0x02, 0x03])); 100 | } catch (e) { 101 | error = e; 102 | } 103 | expect(error.toString()).toMatch("http request is not a valid membuffer"); 104 | }); 105 | 106 | test("Deployment", async () => { 107 | // create sender account 108 | const sender = Orbs.createAccount(); 109 | 110 | // create receiver account 111 | const receiver = Orbs.createAccount(); 112 | 113 | // create client 114 | const endpoint = gammeDriver.getEndpoint(); 115 | const client = new Orbs.Client(endpoint, VIRTUAL_CHAIN_ID, "TEST_NET", new Orbs.LocalSigner(sender)); 116 | 117 | const sources = [ 118 | readFileSync(`${__dirname}/../contract/increment_base.go`), 119 | readFileSync(`${__dirname}/../contract/increment_functions.go`) 120 | ]; 121 | 122 | // create transfer transaction 123 | const [deploymentTx, deploymentTxId] = await client.createDeployTransaction("Inc", Orbs.PROCESSOR_TYPE_NATIVE, ...sources); 124 | 125 | // send the transaction 126 | const deploymentResponse = await client.sendTransaction(deploymentTx); 127 | console.log("Deployment response:"); 128 | console.log(deploymentResponse); 129 | expect(deploymentResponse.requestStatus).toEqual("COMPLETED"); 130 | expect(deploymentResponse.executionResult).toEqual("SUCCESS"); 131 | expect(deploymentResponse.transactionStatus).toEqual("COMMITTED"); 132 | 133 | // create transfer transaction 134 | const [tx, txId] = await client.createTransaction("BenchmarkToken", "transfer", [Orbs.argUint64(10), Orbs.argAddress(receiver.address)]); 135 | 136 | // send the transaction 137 | const transferResponse = await client.sendTransaction(tx); 138 | console.log("Transfer response:"); 139 | console.log(transferResponse); 140 | expect(transferResponse.requestStatus).toEqual("COMPLETED"); 141 | expect(transferResponse.executionResult).toEqual("SUCCESS"); 142 | expect(transferResponse.transactionStatus).toEqual("COMMITTED"); 143 | 144 | // create balance query 145 | const query = await client.createQuery("BenchmarkToken", "getBalance", [Orbs.argAddress(receiver.address)]); 146 | 147 | // send the query 148 | const balanceResponse = await client.sendQuery(query); 149 | console.log("Query response:"); 150 | console.log(balanceResponse); 151 | expect(balanceResponse.requestStatus).toEqual("COMPLETED"); 152 | expect(balanceResponse.executionResult).toEqual("SUCCESS"); 153 | expect(balanceResponse.outputArguments[0]).toEqual(Orbs.argUint64(10)); 154 | 155 | const found = await client.getTransactionStatus(txId); 156 | expect(found.transactionStatus).toEqual("COMMITTED") 157 | 158 | const notFound = await client.getTransactionStatus("0xC0058950d1Bdde15d06C2d7354C3Cb15Dae02CFC6BF5934b358D43dEf1DFE1a0C420Da72e541bd6e") 159 | expect(notFound.transactionStatus).toEqual("NO_RECORD_FOUND"); 160 | }); 161 | }); 162 | -------------------------------------------------------------------------------- /jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | launch: { 3 | headless: true, 4 | args: ["--disable-web-security"], 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "roots": [ 3 | "/src", 4 | "/e2e", 5 | ], 6 | "transform": { 7 | "^.+\\.tsx?$": "ts-jest", 8 | }, 9 | "testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(t|j)sx?$", 10 | "moduleFileExtensions": [ 11 | "ts", 12 | "tsx", 13 | "js", 14 | "jsx", 15 | "json", 16 | "node" 17 | ], 18 | "preset": "jest-puppeteer" 19 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "orbs-client-sdk", 3 | "version": "2.5.0", 4 | "description": "orbs-client-sdk", 5 | "main": "dist/orbs-client-sdk.js", 6 | "browser": "dist/orbs-client-sdk-web.js", 7 | "files": [ 8 | "dist" 9 | ], 10 | "types": "dist/lib.d.ts", 11 | "repository": "https://github.com/orbs-network/orbs-client-sdk-javascript", 12 | "author": "Orbs Team", 13 | "license": "MIT", 14 | "scripts": { 15 | "clean": "rimraf dist", 16 | "build": "npm run clean && npm run build-webpack && npm run types", 17 | "build-webpack": "cross-env NODE_ENV=production webpack -p", 18 | "types": "tsc -p tsconfig-for-types.json", 19 | "dev": "webpack-dev-server -w", 20 | "test": "jest --runInBand", 21 | "lint": "tslint -c tslint.json", 22 | "prepare": "rimraf ./contract && git clone https://github.com/orbs-network/orbs-client-sdk-go.git ./contract" 23 | }, 24 | "prettier": { 25 | "trailingComma": "all", 26 | "tabWidth": 2, 27 | "semi": true, 28 | "singleQuote": false, 29 | "printWidth": 240 30 | }, 31 | "devDependencies": { 32 | "@babel/core": "^7.2.2", 33 | "@babel/plugin-proposal-class-properties": "^7.2.3", 34 | "@babel/plugin-proposal-object-rest-spread": "^7.2.0", 35 | "@babel/plugin-transform-runtime": "^7.2.0", 36 | "@babel/preset-env": "^7.2.3", 37 | "@babel/preset-typescript": "^7.1.0", 38 | "@babel/runtime": "^7.2.0", 39 | "@types/jest": "^23.3.9", 40 | "@types/node": "^10.12.2", 41 | "babel-jest": "^24.8.0", 42 | "babel-loader": "^8.0.5", 43 | "babel-preset-env": "^1.7.0", 44 | "cross-env": "^6.0.3", 45 | "http-server": "^0.12.2", 46 | "jest": "^24.8.0", 47 | "jest-puppeteer": "^3.8.0", 48 | "puppeteer": "^1.9.0", 49 | "rimraf": "^2.6.3", 50 | "ts-jest": "^23.10.4", 51 | "tslib": "^1.9.3", 52 | "tslint": "^5.11.0", 53 | "typescript": "^3.2.4", 54 | "webpack": "^4.28.4", 55 | "webpack-cli": "^3.2.1", 56 | "webpack-dev-server": "^3.7.2" 57 | }, 58 | "dependencies": { 59 | "axios": "^0.18.0", 60 | "elliptic": "^6.4.1", 61 | "fast-text-encoding": "^1.0.0", 62 | "get-random-values": "^1.2.0", 63 | "hash.js": "^1.1.5", 64 | "jest-environment-node": "^25.4.0", 65 | "membuffers": "^0.3.6" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/codec/Arguments.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import { addressToBytes } from ".."; 10 | import { InternalMessage } from "membuffers"; 11 | import * as Protocol from "../protocol/Protocol"; 12 | 13 | export type Argument = ArgBool | ArgUint32 | ArgUint64 | ArgUint256 | ArgString | ArgBytes | ArgBytes20 | ArgBytes32 | 14 | ArgBoolArray | ArgUint32Array | ArgUint64Array | ArgUint256Array | ArgStringArray | ArgBytesArray | ArgBytes20Array | ArgBytes32Array; 15 | 16 | export type ArgBool = { 17 | type: "bool"; 18 | value: boolean; 19 | }; 20 | 21 | export type ArgBoolArray = { 22 | type: "boolArray"; 23 | value: Array; 24 | }; 25 | 26 | export type ArgUint32 = { 27 | type: "uint32"; 28 | value: number; 29 | }; 30 | 31 | export type ArgUint32Array = { 32 | type: "uint32Array"; 33 | value: Array; 34 | }; 35 | 36 | export type ArgUint64 = { 37 | type: "uint64"; 38 | value: bigint; 39 | }; 40 | 41 | export type ArgUint64Array = { 42 | type: "uint64Array"; 43 | value: Array; 44 | }; 45 | 46 | export type ArgUint256 = { 47 | type: "uint256"; 48 | value: bigint; 49 | }; 50 | 51 | export type ArgUint256Array = { 52 | type: "uint256Array"; 53 | value: Array; 54 | }; 55 | 56 | export type ArgString = { 57 | type: "string"; 58 | value: string; 59 | }; 60 | 61 | export type ArgStringArray = { 62 | type: "stringArray"; 63 | value: Array; 64 | }; 65 | 66 | export type ArgBytes = { 67 | type: "bytes"; 68 | value: Uint8Array; 69 | }; 70 | 71 | export type ArgBytesArray = { 72 | type: "bytesArray"; 73 | value: Array; 74 | }; 75 | 76 | export type ArgBytes20 = { 77 | type: "bytes20"; 78 | value: Uint8Array; 79 | }; 80 | 81 | export type ArgBytes20Array = { 82 | type: "bytes20Array"; 83 | value: Array; 84 | }; 85 | 86 | export type ArgBytes32 = { 87 | type: "bytes32"; 88 | value: Uint8Array; 89 | }; 90 | 91 | export type ArgBytes32Array = { 92 | type: "bytes32Array"; 93 | value: Array; 94 | }; 95 | 96 | export const argBool = (value: boolean): ArgBool => ({ 97 | type: "bool", 98 | value, 99 | }); 100 | 101 | export const argBoolArray = (value: Array): ArgBoolArray => ({ 102 | type: "boolArray", 103 | value, 104 | }); 105 | 106 | export const argUint32 = (value: number): ArgUint32 => ({ 107 | type: "uint32", 108 | value, 109 | }); 110 | 111 | export const argUint32Array = (value: Array): ArgUint32Array => ({ 112 | type: "uint32Array", 113 | value, 114 | }); 115 | 116 | export const argUint64 = (value: bigint | number): ArgUint64 => ({ 117 | type: "uint64", 118 | value: typeof value === "number" ? BigInt(value) : value, 119 | }); 120 | 121 | export const argUint64Array = (value: Array): ArgUint64Array => ({ 122 | type: "uint64Array", 123 | value, 124 | }); 125 | 126 | export const argUint256 = (value: bigint): ArgUint256 => ({ 127 | type: "uint256", 128 | value, 129 | }); 130 | 131 | export const argUint256Array = (value: Array): ArgUint256Array => ({ 132 | type: "uint256Array", 133 | value, 134 | }); 135 | 136 | export const argString = (value: string): ArgString => ({ 137 | type: "string", 138 | value, 139 | }); 140 | 141 | export const argStringArray = (value: Array): ArgStringArray => ({ 142 | type: "stringArray", 143 | value, 144 | }); 145 | 146 | export const argBytes = (value: Uint8Array): ArgBytes => ({ 147 | type: "bytes", 148 | value, 149 | }); 150 | 151 | export const argBytesArray = (value: Array): ArgBytesArray => ({ 152 | type: "bytesArray", 153 | value, 154 | }); 155 | 156 | export const argBytes20 = (value: Uint8Array): ArgBytes20 => ({ 157 | type: "bytes20", 158 | value, 159 | }); 160 | 161 | export const argBytes20Array = (value: Array): ArgBytes20Array => ({ 162 | type: "bytes20Array", 163 | value, 164 | }); 165 | 166 | export const argBytes32 = (value: Uint8Array): ArgBytes32 => ({ 167 | type: "bytes32", 168 | value, 169 | }); 170 | 171 | export const argBytes32Array = (value: Array): ArgBytes32Array => ({ 172 | type: "bytes32Array", 173 | value, 174 | }); 175 | 176 | export const argAddress = (address: string) => argBytes(addressToBytes(address)); 177 | 178 | function argumentsBuilders(args: Argument[]): Protocol.ArgumentBuilder[] { 179 | const res: Protocol.ArgumentBuilder[] = []; 180 | for (let i = 0; i < args.length; i++) { 181 | const arg = args[i]; 182 | let type = -1; 183 | switch (arg.type) { 184 | case "uint32": 185 | type = Protocol.ARGUMENT_TYPE_UINT_32_VALUE; 186 | break; 187 | case "uint64": 188 | type = Protocol.ARGUMENT_TYPE_UINT_64_VALUE; 189 | break; 190 | case "string": 191 | type = Protocol.ARGUMENT_TYPE_STRING_VALUE; 192 | break; 193 | case "bytes": 194 | type = Protocol.ARGUMENT_TYPE_BYTES_VALUE; 195 | break; 196 | case "bool": 197 | type = Protocol.ARGUMENT_TYPE_BOOL_VALUE; 198 | break; 199 | case "uint256": 200 | type = Protocol.ARGUMENT_TYPE_UINT_256_VALUE; 201 | break; 202 | case "bytes20": 203 | type = Protocol.ARGUMENT_TYPE_BYTES_20_VALUE; 204 | break; 205 | case "bytes32": 206 | type = Protocol.ARGUMENT_TYPE_BYTES_32_VALUE; 207 | break; 208 | case "uint32Array": 209 | type = Protocol.ARGUMENT_TYPE_UINT_32_ARRAY_VALUE; 210 | break; 211 | case "uint64Array": 212 | type = Protocol.ARGUMENT_TYPE_UINT_64_ARRAY_VALUE; 213 | break; 214 | case "stringArray": 215 | type = Protocol.ARGUMENT_TYPE_STRING_ARRAY_VALUE; 216 | break; 217 | case "bytesArray": 218 | type = Protocol.ARGUMENT_TYPE_BYTES_ARRAY_VALUE; 219 | break; 220 | case "boolArray": 221 | type = Protocol.ARGUMENT_TYPE_BOOL_ARRAY_VALUE; 222 | break; 223 | case "uint256Array": 224 | type = Protocol.ARGUMENT_TYPE_UINT_256_ARRAY_VALUE; 225 | break; 226 | case "bytes20Array": 227 | type = Protocol.ARGUMENT_TYPE_BYTES_20_ARRAY_VALUE; 228 | break; 229 | case "bytes32Array": 230 | type = Protocol.ARGUMENT_TYPE_BYTES_32_ARRAY_VALUE; 231 | break; 232 | default: 233 | throw new Error(`Argument unknown type: ${arg}`); 234 | } 235 | res.push(new Protocol.ArgumentBuilder({ type: type, value: arg.value })); 236 | } 237 | return res; 238 | } 239 | 240 | function argumentsArray(args: Argument[]): InternalMessage { 241 | const builders = argumentsBuilders(args); 242 | const buf = new Protocol.ArgumentArrayBuilder({ arguments: builders }).build(); 243 | return new InternalMessage(buf, buf.byteLength, Protocol.ArgumentArray_Scheme, []); 244 | } 245 | 246 | export function packedArgumentsEncode(args: Argument[]): Uint8Array { 247 | const msg = argumentsArray(args); 248 | return msg.rawBufferForField(0, 0); 249 | } 250 | 251 | export function packedArgumentsDecode(buf: Uint8Array): Argument[] { 252 | const res: Argument[] = []; 253 | const argsArrayMsg = new InternalMessage(buf, buf.byteLength, Protocol.ArgumentArray_Scheme, []); 254 | const iterator = argsArrayMsg.getMessageArrayIterator(0); 255 | let index = 0; 256 | while (iterator.hasNext()) { 257 | const [argumentBuf, argumentBufLength] = iterator.nextMessage(); 258 | const argumentMsg = new InternalMessage(argumentBuf, argumentBufLength, Protocol.Argument_Scheme, Protocol.Argument_Unions); 259 | const type = argumentMsg.getUnionIndex(0, 0); 260 | switch (type) { 261 | case Protocol.ARGUMENT_TYPE_UINT_32_VALUE: 262 | const [, uint32Off] = argumentMsg.isUnionIndex(0, 0, 0); 263 | res.push(argUint32(argumentMsg.getUint32InOffset(uint32Off))); 264 | break; 265 | case Protocol.ARGUMENT_TYPE_UINT_64_VALUE: 266 | const [, uint64Off] = argumentMsg.isUnionIndex(0, 0, 1); 267 | res.push(argUint64(argumentMsg.getUint64InOffset(uint64Off))); 268 | break; 269 | case Protocol.ARGUMENT_TYPE_STRING_VALUE: 270 | const [, stringOff] = argumentMsg.isUnionIndex(0, 0, 2); 271 | res.push(argString(argumentMsg.getStringInOffset(stringOff))); 272 | break; 273 | case Protocol.ARGUMENT_TYPE_BYTES_VALUE: 274 | const [, bytesOff] = argumentMsg.isUnionIndex(0, 0, 3); 275 | res.push(argBytes(argumentMsg.getBytesInOffset(bytesOff))); 276 | break; 277 | case Protocol.ARGUMENT_TYPE_BOOL_VALUE: 278 | const [, boolOff] = argumentMsg.isUnionIndex(0, 0, 4); 279 | res.push(argBool(argumentMsg.getBoolInOffset(boolOff))); 280 | break; 281 | case Protocol.ARGUMENT_TYPE_UINT_256_VALUE: 282 | const [, uint256Off] = argumentMsg.isUnionIndex(0, 0, 5); 283 | res.push(argUint256(argumentMsg.getUint256InOffset(uint256Off))); 284 | break; 285 | case Protocol.ARGUMENT_TYPE_BYTES_20_VALUE: 286 | const [, bytes20Off] = argumentMsg.isUnionIndex(0, 0, 6); 287 | res.push(argBytes20(argumentMsg.getBytes20InOffset(bytes20Off))); 288 | break; 289 | case Protocol.ARGUMENT_TYPE_BYTES_32_VALUE: 290 | const [, bytes32Off] = argumentMsg.isUnionIndex(0, 0, 7); 291 | res.push(argBytes32(argumentMsg.getBytes32InOffset(bytes32Off))); 292 | break; 293 | case Protocol.ARGUMENT_TYPE_UINT_32_ARRAY_VALUE: 294 | const [, uint32ArrayOff] = argumentMsg.isUnionIndex(0, 0, 8); 295 | const uint32ArrayItr = argumentMsg.getUint32ArrayIteratorInOffset(uint32ArrayOff); 296 | const uint32Array = new Array(0); 297 | while (uint32ArrayItr.hasNext()) { 298 | uint32Array.push(uint32ArrayItr.nextUint32()); 299 | } 300 | res.push(argUint32Array(uint32Array)); 301 | break; 302 | case Protocol.ARGUMENT_TYPE_UINT_64_ARRAY_VALUE: 303 | const [, uint64ArrayOff] = argumentMsg.isUnionIndex(0, 0, 9); 304 | const uint64ArrayItr = argumentMsg.getUint64ArrayIteratorInOffset(uint64ArrayOff); 305 | const uint64Array = new Array(0); 306 | while (uint64ArrayItr.hasNext()) { 307 | uint64Array.push(uint64ArrayItr.nextUint64()); 308 | } 309 | res.push(argUint64Array(uint64Array)); 310 | break; 311 | case Protocol.ARGUMENT_TYPE_STRING_ARRAY_VALUE: 312 | const [, stringArrayOff] = argumentMsg.isUnionIndex(0, 0, 10); 313 | const stringArrayItr = argumentMsg.getStringArrayIteratorInOffset(stringArrayOff); 314 | const stringArray = new Array(0); 315 | while (stringArrayItr.hasNext()) { 316 | stringArray.push(stringArrayItr.nextString()); 317 | } 318 | res.push(argStringArray(stringArray)); 319 | break; 320 | case Protocol.ARGUMENT_TYPE_BYTES_ARRAY_VALUE: 321 | const [, bytesArrayOff] = argumentMsg.isUnionIndex(0, 0, 11); 322 | const bytesArrayItr = argumentMsg.getBytesArrayIteratorInOffset(bytesArrayOff); 323 | const bytesArray = new Array(0); 324 | while (bytesArrayItr.hasNext()) { 325 | bytesArray.push(bytesArrayItr.nextBytes()); 326 | } 327 | res.push(argBytesArray(bytesArray)); 328 | break; 329 | case Protocol.ARGUMENT_TYPE_BOOL_ARRAY_VALUE: 330 | const [, boolArrayOff] = argumentMsg.isUnionIndex(0, 0, 12); 331 | const boolArrayItr = argumentMsg.getBoolArrayIteratorInOffset(boolArrayOff); 332 | const boolArray = new Array(0); 333 | while (boolArrayItr.hasNext()) { 334 | boolArray.push(boolArrayItr.nextBool()); 335 | } 336 | res.push(argBoolArray(boolArray)); 337 | break; 338 | case Protocol.ARGUMENT_TYPE_UINT_256_ARRAY_VALUE: 339 | const [, uint256ArrayOff] = argumentMsg.isUnionIndex(0, 0, 13); 340 | const uint256ArrayItr = argumentMsg.getUint256ArrayIteratorInOffset(uint256ArrayOff); 341 | const uint256Array = new Array(0); 342 | while (uint256ArrayItr.hasNext()) { 343 | uint256Array.push(uint256ArrayItr.nextUint256()); 344 | } 345 | res.push(argUint256Array(uint256Array)); 346 | break; 347 | case Protocol.ARGUMENT_TYPE_BYTES_20_ARRAY_VALUE: 348 | const [, bytes20ArrayOff] = argumentMsg.isUnionIndex(0, 0, 14); 349 | const bytes20ArrayItr = argumentMsg.getBytes20ArrayIteratorInOffset(bytes20ArrayOff); 350 | const bytes20Array = new Array(0); 351 | while (bytes20ArrayItr.hasNext()) { 352 | bytes20Array.push(bytes20ArrayItr.nextBytes20()); 353 | } 354 | res.push(argBytes20Array(bytes20Array)); 355 | break; 356 | case Protocol.ARGUMENT_TYPE_BYTES_32_ARRAY_VALUE: 357 | const [, bytes32ArrayOff] = argumentMsg.isUnionIndex(0, 0, 15); 358 | const bytes32ArrayItr = argumentMsg.getBytes32ArrayIteratorInOffset(bytes32ArrayOff); 359 | const bytes32Array = new Array(0); 360 | while (bytes32ArrayItr.hasNext()) { 361 | bytes32Array.push(bytes32ArrayItr.nextBytes32()); 362 | } 363 | res.push(argBytes32Array(bytes32Array)); 364 | break; 365 | default: 366 | throw new Error(`received argument ${index} has unknown type: ${type}`); 367 | } 368 | index++; 369 | } 370 | return res; 371 | } 372 | -------------------------------------------------------------------------------- /src/codec/Events.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import { Argument, packedArgumentsDecode } from "./Arguments"; 10 | import { InternalMessage } from "membuffers"; 11 | import * as Protocol from "../protocol/Protocol"; 12 | 13 | export interface Event { 14 | contractName: string; 15 | eventName: string; 16 | arguments: Argument[]; 17 | } 18 | 19 | export function packedEventsDecode(buf: Uint8Array): Event[] { 20 | const res: Event[] = []; 21 | const eventsArrayMsg = new InternalMessage(buf, buf.byteLength, Protocol.EventsArray_Scheme, []); 22 | const iterator = eventsArrayMsg.getMessageArrayIterator(0); 23 | let index = 0; 24 | while (iterator.hasNext()) { 25 | const [eventBuf, eventBufLength] = iterator.nextMessage(); 26 | const eventMsg = new InternalMessage(eventBuf, eventBufLength, Protocol.Event_Scheme, []); 27 | res.push({ 28 | contractName: eventMsg.getString(0), 29 | eventName: eventMsg.getString(1), 30 | arguments: packedArgumentsDecode(eventMsg.rawBufferWithHeaderForField(2, 0)), 31 | }); 32 | index++; 33 | } 34 | return res; 35 | } 36 | -------------------------------------------------------------------------------- /src/codec/ExecutionResult.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | export enum ExecutionResult { 10 | EXECUTION_RESULT_SUCCESS = "SUCCESS", 11 | EXECUTION_RESULT_ERROR_SMART_CONTRACT = "ERROR_SMART_CONTRACT", 12 | EXECUTION_RESULT_ERROR_INPUT = "ERROR_INPUT", 13 | EXECUTION_RESULT_ERROR_CONTRACT_NOT_DEPLOYED = "ERROR_CONTRACT_NOT_DEPLOYED", 14 | EXECUTION_RESULT_ERROR_UNEXPECTED = "ERROR_UNEXPECTED", 15 | EXECUTION_RESULT_NOT_EXECUTED = "NOT_EXECUTED", 16 | } 17 | 18 | export function executionResultDecode(executionResult: number): ExecutionResult { 19 | switch (executionResult) { 20 | case 0: 21 | throw new Error(`reserved ExecutionResult received`); 22 | case 1: 23 | return ExecutionResult.EXECUTION_RESULT_SUCCESS; 24 | case 2: 25 | return ExecutionResult.EXECUTION_RESULT_ERROR_SMART_CONTRACT; 26 | case 3: 27 | return ExecutionResult.EXECUTION_RESULT_ERROR_INPUT; 28 | case 4: 29 | return ExecutionResult.EXECUTION_RESULT_ERROR_CONTRACT_NOT_DEPLOYED; 30 | case 5: 31 | return ExecutionResult.EXECUTION_RESULT_ERROR_UNEXPECTED; 32 | case 6: 33 | return ExecutionResult.EXECUTION_RESULT_NOT_EXECUTED; 34 | default: 35 | throw new Error(`unsupported ExecutionResult received: ${executionResult}`); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/codec/NetworkType.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | export enum NetworkType { 10 | NETWORK_TYPE_MAIN_NET = "MAIN_NET", 11 | NETWORK_TYPE_TEST_NET = "TEST_NET", 12 | } 13 | 14 | export function networkTypeEncode(networkType: NetworkType): number { 15 | switch (networkType) { 16 | case NetworkType.NETWORK_TYPE_MAIN_NET: 17 | return 77; 18 | case NetworkType.NETWORK_TYPE_TEST_NET: 19 | return 84; 20 | default: 21 | throw new Error(`unsupported network type given ${networkType}`); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/codec/OpGetBlock.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import * as Hash from "../crypto/Hash"; 10 | import * as Digest from "../crypto/Digest"; 11 | import * as Client from "../protocol/Client"; 12 | import * as Protocol from "../protocol/Protocol"; 13 | import { InternalMessage } from "membuffers"; 14 | import { RequestStatus, requestStatusDecode } from "./RequestStatus"; 15 | import { ExecutionResult, executionResultDecode } from "./ExecutionResult"; 16 | import { Argument, packedArgumentsDecode } from "./Arguments"; 17 | import { Event, packedEventsDecode } from "./Events"; 18 | 19 | export interface GetBlockRequest { 20 | protocolVersion: number; 21 | virtualChainId: number; 22 | blockHeight: bigint; 23 | } 24 | 25 | export interface GetBlockResponse { 26 | requestStatus: RequestStatus; 27 | blockHeight: bigint; 28 | blockTimestamp: Date; 29 | transactionsBlockHash: Uint8Array; 30 | transactionsBlockHeader: TransactionsBlockHeader; 31 | resultsBlockHash: Uint8Array; 32 | resultsBlockHeader: ResultsBlockHeader; 33 | transactions: BlockTransaction[]; 34 | } 35 | 36 | export interface TransactionsBlockHeader { 37 | protocolVersion: number; 38 | virtualChainId: number; 39 | blockHeight: bigint; 40 | prevBlockHash: Uint8Array; 41 | timestamp: Date; 42 | numTransactions: number; 43 | referenceTime: number; 44 | blockProposerAddress: Uint8Array; 45 | } 46 | 47 | export interface ResultsBlockHeader { 48 | protocolVersion: number; 49 | virtualChainId: number; 50 | blockHeight: bigint; 51 | prevBlockHash: Uint8Array; 52 | timestamp: Date; 53 | transactionsBlockHash: Uint8Array; 54 | numTransactionReceipts: number; 55 | referenceTime: number; 56 | blockProposerAddress: Uint8Array; 57 | } 58 | 59 | export interface BlockTransaction { 60 | txId: Uint8Array; 61 | txHash: Uint8Array; 62 | protocolVersion: number; 63 | virtualChainId: number; 64 | timestamp: Date; 65 | signerPublicKey: Uint8Array; 66 | contractName: string; 67 | methodName: string; 68 | inputArguments: Argument[]; 69 | executionResult: ExecutionResult; 70 | outputArguments: Argument[]; 71 | outputEvents: Event[]; 72 | } 73 | 74 | export function encodeGetBlockRequest(req: GetBlockRequest): Uint8Array { 75 | // validate 76 | if (req.protocolVersion != 1) { 77 | throw new Error(`expected ProtocolVersion 1, ${req.protocolVersion} given`); 78 | } 79 | 80 | // encode request 81 | const res = new Client.GetBlockRequestBuilder({ 82 | protocolVersion: req.protocolVersion, 83 | virtualChainId: req.virtualChainId, 84 | blockHeight: req.blockHeight, 85 | }); 86 | 87 | // return 88 | return res.build(); 89 | } 90 | 91 | export function decodeGetBlockResponse(buf: Uint8Array): GetBlockResponse { 92 | // decode response 93 | const getBlockResponseMsg = new InternalMessage(buf, buf.byteLength, Client.GetBlockResponse_Scheme, []); 94 | if (!getBlockResponseMsg.isValid()) { 95 | throw new Error(`response is corrupt and cannot be decoded`); 96 | } 97 | 98 | // decode request status 99 | const requestResultBuf = getBlockResponseMsg.getMessage(0); 100 | const requestResultMsg = new InternalMessage(requestResultBuf, requestResultBuf.byteLength, Client.RequestResult_Scheme, []); 101 | const requestStatus = requestStatusDecode(requestResultMsg.getUint16(0)); 102 | 103 | // decode transactions block header 104 | const transactionsBlockHeaderBuf = getBlockResponseMsg.getMessage(1); 105 | const transactionsBlockHeaderMsg = new InternalMessage(transactionsBlockHeaderBuf, transactionsBlockHeaderBuf.byteLength, Protocol.TransactionsBlockHeader_Scheme, []); 106 | 107 | // decode results block header 108 | const resultsBlockHeaderBuf = getBlockResponseMsg.getMessage(5); 109 | const resultsBlockHeaderMsg = new InternalMessage(resultsBlockHeaderBuf, resultsBlockHeaderBuf.byteLength, Protocol.ResultsBlockHeader_Scheme, []); 110 | 111 | // decode transactions 112 | const transactions: BlockTransaction[] = []; 113 | const txIterator = getBlockResponseMsg.getMessageArrayIterator(3); 114 | for (const tx of txIterator) { 115 | const [txBuf]: any = tx; 116 | const txMsg = new InternalMessage(txBuf, txBuf.byteLength, Protocol.SignedTransaction_Scheme, []); 117 | const transactionBuf = txMsg.getMessage(0); 118 | const transactionMsg = new InternalMessage(transactionBuf, transactionBuf.byteLength, Protocol.Transaction_Scheme, []); 119 | 120 | // decode method arguments 121 | const inputArgumentArray = packedArgumentsDecode(transactionMsg.rawBufferWithHeaderForField(6, 0)); 122 | 123 | // decode signer 124 | let signerPublicKey: Uint8Array = undefined; 125 | const signerBuf = transactionMsg.getMessage(3); 126 | const signerMsg = new InternalMessage(signerBuf, signerBuf.byteLength, Protocol.Signer_Scheme, Protocol.Signer_Unions); 127 | const [isEddsaSigner, eddsaSignerOff] = signerMsg.isUnionIndex(0, 0, 0); 128 | if (isEddsaSigner) { 129 | const eddsaSignerBuf = signerMsg.getMessageInOffset(eddsaSignerOff); 130 | const eddsaSignerMsg = new InternalMessage(eddsaSignerBuf, eddsaSignerBuf.byteLength, Protocol.EdDSA01Signer_Scheme, []); 131 | signerPublicKey = eddsaSignerMsg.getBytes(1); 132 | } 133 | 134 | // add transaction 135 | const txHash = Digest.calcTxHash(transactionBuf); 136 | const txTimestamp = transactionMsg.getUint64(2); 137 | transactions.push({ 138 | txHash: txHash, 139 | txId: Digest.generateTxId(txHash, txTimestamp), 140 | protocolVersion: transactionMsg.getUint32(0), 141 | virtualChainId: transactionMsg.getUint32(1), 142 | timestamp: Protocol.unixNanoToDate(txTimestamp), 143 | signerPublicKey: signerPublicKey, 144 | contractName: transactionMsg.getString(4), 145 | methodName: transactionMsg.getString(5), 146 | inputArguments: inputArgumentArray, 147 | executionResult: undefined, 148 | outputArguments: undefined, 149 | outputEvents: undefined, 150 | }); 151 | } 152 | 153 | // decode receipts 154 | const receiptIterator = getBlockResponseMsg.getMessageArrayIterator(6); 155 | for (const receipt of receiptIterator) { 156 | const [receiptBuf]: any = receipt; 157 | const receiptMsg = new InternalMessage(receiptBuf, receiptBuf.byteLength, Protocol.TransactionReceipt_Scheme, []); 158 | const receiptTxHash = receiptMsg.getBytes(0); 159 | for (const transaction of transactions) { 160 | if (uint8ArrayEquals(transaction.txHash, receiptTxHash)) { 161 | // decode execution result 162 | const executionResult = executionResultDecode(receiptMsg.getUint16(1)); 163 | transaction.executionResult = executionResult; 164 | 165 | // decode method arguments 166 | const outputArgumentArray = packedArgumentsDecode(receiptMsg.rawBufferWithHeaderForField(2, 0)); 167 | transaction.outputArguments = outputArgumentArray; 168 | 169 | // decode events 170 | const outputEventArray = packedEventsDecode(receiptMsg.rawBufferWithHeaderForField(3, 0)); 171 | transaction.outputEvents = outputEventArray; 172 | } 173 | } 174 | } 175 | 176 | // return 177 | return { 178 | requestStatus: requestStatus, 179 | blockHeight: requestResultMsg.getUint64(1), 180 | blockTimestamp: Protocol.unixNanoToDate(requestResultMsg.getUint64(2)), 181 | transactionsBlockHash: Hash.calcSha256(transactionsBlockHeaderMsg.rawBuffer()), 182 | transactionsBlockHeader: { 183 | protocolVersion: transactionsBlockHeaderMsg.getUint32(0), 184 | virtualChainId: transactionsBlockHeaderMsg.getUint32(1), 185 | blockHeight: transactionsBlockHeaderMsg.getUint64(2), 186 | prevBlockHash: transactionsBlockHeaderMsg.getBytes(3), 187 | timestamp: Protocol.unixNanoToDate(transactionsBlockHeaderMsg.getUint64(4)), 188 | numTransactions: transactionsBlockHeaderMsg.getUint32(7), 189 | referenceTime: transactionsBlockHeaderMsg.getUint32(9), 190 | blockProposerAddress: transactionsBlockHeaderMsg.getBytes(8) 191 | }, 192 | resultsBlockHash: Hash.calcSha256(resultsBlockHeaderMsg.rawBuffer()), 193 | resultsBlockHeader: { 194 | protocolVersion: resultsBlockHeaderMsg.getUint32(0), 195 | virtualChainId: resultsBlockHeaderMsg.getUint32(1), 196 | blockHeight: resultsBlockHeaderMsg.getUint64(2), 197 | prevBlockHash: resultsBlockHeaderMsg.getBytes(3), 198 | timestamp: Protocol.unixNanoToDate(resultsBlockHeaderMsg.getUint64(4)), 199 | transactionsBlockHash: resultsBlockHeaderMsg.getBytes(7), 200 | numTransactionReceipts: resultsBlockHeaderMsg.getUint32(9), 201 | blockProposerAddress: resultsBlockHeaderMsg.getBytes(11), 202 | referenceTime: resultsBlockHeaderMsg.getUint32(12) 203 | }, 204 | transactions: transactions, 205 | }; 206 | } 207 | 208 | function uint8ArrayEquals(a: Uint8Array, b: Uint8Array): boolean { 209 | if (a.byteLength != a.byteLength) { 210 | return false; 211 | } 212 | for (let i = 0; i < a.byteLength; i++) { 213 | if (a[i] != b[i]) { 214 | return false; 215 | } 216 | } 217 | return true; 218 | } 219 | -------------------------------------------------------------------------------- /src/codec/OpGetTransactionReceiptProof.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import * as Digest from "../crypto/Digest"; 10 | import * as Client from "../protocol/Client"; 11 | import * as Protocol from "../protocol/Protocol"; 12 | import { InternalMessage } from "membuffers"; 13 | import { RequestStatus, requestStatusDecode } from "./RequestStatus"; 14 | import { ExecutionResult, executionResultDecode } from "./ExecutionResult"; 15 | import { Argument, packedArgumentsDecode } from "./Arguments"; 16 | import { Event, packedEventsDecode } from "./Events"; 17 | import { TransactionStatus, transactionStatusDecode } from "./TransactionStatus"; 18 | 19 | export interface GetTransactionReceiptProofRequest { 20 | protocolVersion: number; 21 | virtualChainId: number; 22 | txId: Uint8Array; 23 | } 24 | 25 | export interface GetTransactionReceiptProofResponse { 26 | requestStatus: RequestStatus; 27 | txHash: Uint8Array; 28 | executionResult: ExecutionResult; 29 | outputArguments: Argument[]; 30 | outputEvents: Event[]; 31 | transactionStatus: TransactionStatus; 32 | blockHeight: bigint; 33 | blockTimestamp: Date; 34 | packedProof: Uint8Array; 35 | packedReceipt: Uint8Array; 36 | } 37 | 38 | export function encodeGetTransactionReceiptProofRequest(req: GetTransactionReceiptProofRequest): Uint8Array { 39 | // validate 40 | if (req.protocolVersion != 1) { 41 | throw new Error(`expected ProtocolVersion 1, ${req.protocolVersion} given`); 42 | } 43 | if (req.txId.byteLength != Digest.TX_ID_SIZE_BYTES) { 44 | throw new Error(`expected TxId length ${Digest.TX_ID_SIZE_BYTES}, ${req.txId.byteLength} given`); 45 | } 46 | 47 | // extract txid 48 | const [txHash, txTimestamp] = Digest.extractTxId(req.txId); 49 | 50 | // encode request 51 | const res = new Client.GetTransactionReceiptProofRequestBuilder({ 52 | transactionRef: new Client.TransactionRefBuilder({ 53 | protocolVersion: req.protocolVersion, 54 | virtualChainId: req.virtualChainId, 55 | transactionTimestamp: txTimestamp, 56 | txHash: txHash, 57 | }), 58 | }); 59 | 60 | // return 61 | return res.build(); 62 | } 63 | 64 | export function decodeGetTransactionReceiptProofResponse(buf: Uint8Array): GetTransactionReceiptProofResponse { 65 | // decode response 66 | const getTransactionReceiptProofResponseMsg = new InternalMessage(buf, buf.byteLength, Client.GetTransactionReceiptProofResponse_Scheme, []); 67 | if (!getTransactionReceiptProofResponseMsg.isValid()) { 68 | throw new Error(`response is corrupt and cannot be decoded`); 69 | } 70 | 71 | // decode request status 72 | const requestResultBuf = getTransactionReceiptProofResponseMsg.getMessage(0); 73 | const requestResultMsg = new InternalMessage(requestResultBuf, requestResultBuf.byteLength, Client.RequestResult_Scheme, []); 74 | const requestStatus = requestStatusDecode(requestResultMsg.getUint16(0)); 75 | 76 | // decode execution result 77 | const transactionReceiptBuf = getTransactionReceiptProofResponseMsg.getMessage(2); 78 | const transactionReceiptMsg = new InternalMessage(transactionReceiptBuf, transactionReceiptBuf.byteLength, Protocol.TransactionReceipt_Scheme, []); 79 | let executionResult = ExecutionResult.EXECUTION_RESULT_NOT_EXECUTED; 80 | if (transactionReceiptBuf.byteLength > 0) { 81 | executionResult = executionResultDecode(transactionReceiptMsg.getUint16(1)); 82 | } 83 | 84 | // decode method arguments 85 | const outputArgumentArray = packedArgumentsDecode(transactionReceiptMsg.rawBufferWithHeaderForField(2, 0)); 86 | 87 | // decode events 88 | const outputEventArray = packedEventsDecode(transactionReceiptMsg.rawBufferWithHeaderForField(3, 0)); 89 | 90 | // decode transaction status 91 | const transactionStatus = transactionStatusDecode(getTransactionReceiptProofResponseMsg.getUint16(1)); 92 | 93 | // return 94 | return { 95 | requestStatus: requestStatus, 96 | txHash: transactionReceiptMsg.getBytes(0), 97 | executionResult: executionResult, 98 | outputArguments: outputArgumentArray, 99 | outputEvents: outputEventArray, 100 | transactionStatus: transactionStatus, 101 | blockHeight: requestResultMsg.getUint64(1), 102 | blockTimestamp: Protocol.unixNanoToDate(requestResultMsg.getUint64(2)), 103 | packedProof: getTransactionReceiptProofResponseMsg.getBytes(3), 104 | packedReceipt: transactionReceiptBuf, 105 | }; 106 | } 107 | -------------------------------------------------------------------------------- /src/codec/OpGetTransactionStatus.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import * as Digest from "../crypto/Digest"; 10 | import * as Client from "../protocol/Client"; 11 | import * as Protocol from "../protocol/Protocol"; 12 | import { InternalMessage } from "membuffers"; 13 | import { RequestStatus, requestStatusDecode } from "./RequestStatus"; 14 | import { ExecutionResult, executionResultDecode } from "./ExecutionResult"; 15 | import { Argument, packedArgumentsDecode } from "./Arguments"; 16 | import { Event, packedEventsDecode } from "./Events"; 17 | import { TransactionStatus, transactionStatusDecode } from "./TransactionStatus"; 18 | 19 | export interface GetTransactionStatusRequest { 20 | protocolVersion: number; 21 | virtualChainId: number; 22 | txId: Uint8Array; 23 | } 24 | 25 | export interface GetTransactionStatusResponse { 26 | requestStatus: RequestStatus; 27 | txHash: Uint8Array; 28 | executionResult: ExecutionResult; 29 | outputArguments: Argument[]; 30 | outputEvents: Event[]; 31 | transactionStatus: TransactionStatus; 32 | blockHeight: bigint; 33 | blockTimestamp: Date; 34 | } 35 | 36 | export function encodeGetTransactionStatusRequest(req: GetTransactionStatusRequest): Uint8Array { 37 | // validate 38 | if (req.protocolVersion != 1) { 39 | throw new Error(`expected ProtocolVersion 1, ${req.protocolVersion} given`); 40 | } 41 | if (req.txId.byteLength != Digest.TX_ID_SIZE_BYTES) { 42 | throw new Error(`expected TxId length ${Digest.TX_ID_SIZE_BYTES}, ${req.txId.byteLength} given`); 43 | } 44 | 45 | // extract txid 46 | const [txHash, txTimestamp] = Digest.extractTxId(req.txId); 47 | 48 | // encode request 49 | const res = new Client.GetTransactionStatusRequestBuilder({ 50 | transactionRef: new Client.TransactionRefBuilder({ 51 | protocolVersion: req.protocolVersion, 52 | virtualChainId: req.virtualChainId, 53 | transactionTimestamp: txTimestamp, 54 | txHash: txHash, 55 | }), 56 | }); 57 | 58 | // return 59 | return res.build(); 60 | } 61 | 62 | export function decodeGetTransactionStatusResponse(buf: Uint8Array): GetTransactionStatusResponse { 63 | // decode response 64 | const getTransactionStatusResponseMsg = new InternalMessage(buf, buf.byteLength, Client.GetTransactionStatusResponse_Scheme, []); 65 | if (!getTransactionStatusResponseMsg.isValid()) { 66 | throw new Error(`response is corrupt and cannot be decoded`); 67 | } 68 | 69 | // decode request status 70 | const requestResultBuf = getTransactionStatusResponseMsg.getMessage(0); 71 | const requestResultMsg = new InternalMessage(requestResultBuf, requestResultBuf.byteLength, Client.RequestResult_Scheme, []); 72 | const requestStatus = requestStatusDecode(requestResultMsg.getUint16(0)); 73 | 74 | // decode execution result 75 | const transactionReceiptBuf = getTransactionStatusResponseMsg.getMessage(2); 76 | const transactionReceiptMsg = new InternalMessage(transactionReceiptBuf, transactionReceiptBuf.byteLength, Protocol.TransactionReceipt_Scheme, []); 77 | let executionResult = ExecutionResult.EXECUTION_RESULT_NOT_EXECUTED; 78 | if (transactionReceiptBuf.byteLength > 0) { 79 | executionResult = executionResultDecode(transactionReceiptMsg.getUint16(1)); 80 | } 81 | 82 | // decode method arguments 83 | const outputArgumentArray = packedArgumentsDecode(transactionReceiptMsg.rawBufferWithHeaderForField(2, 0)); 84 | 85 | // decode events 86 | const outputEventArray = packedEventsDecode(transactionReceiptMsg.rawBufferWithHeaderForField(3, 0)); 87 | 88 | // decode transaction status 89 | const transactionStatus = transactionStatusDecode(getTransactionStatusResponseMsg.getUint16(1)); 90 | 91 | // return 92 | return { 93 | requestStatus: requestStatus, 94 | txHash: transactionReceiptMsg.getBytes(0), 95 | executionResult: executionResult, 96 | outputArguments: outputArgumentArray, 97 | outputEvents: outputEventArray, 98 | transactionStatus: transactionStatus, 99 | blockHeight: requestResultMsg.getUint64(1), 100 | blockTimestamp: Protocol.unixNanoToDate(requestResultMsg.getUint64(2)), 101 | }; 102 | } 103 | -------------------------------------------------------------------------------- /src/codec/OpRunQuery.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import * as Client from "../protocol/Client"; 10 | import * as Protocol from "../protocol/Protocol"; 11 | import { InternalMessage } from "membuffers"; 12 | import { NetworkType, networkTypeEncode } from "./NetworkType"; 13 | import { RequestStatus, requestStatusDecode } from "./RequestStatus"; 14 | import { ExecutionResult, executionResultDecode } from "./ExecutionResult"; 15 | import { Argument, packedArgumentsDecode, packedArgumentsEncode } from "./Arguments"; 16 | import { Event, packedEventsDecode } from "./Events"; 17 | import { Signer } from "../crypto/Signer"; 18 | 19 | export interface RunQueryRequest { 20 | protocolVersion: number; 21 | virtualChainId: number; 22 | timestamp: Date; 23 | networkType: NetworkType; 24 | contractName: string; 25 | methodName: string; 26 | inputArguments: Argument[]; 27 | } 28 | 29 | export interface RunQueryResponse { 30 | requestStatus: RequestStatus; 31 | executionResult: ExecutionResult; 32 | outputArguments: Argument[]; 33 | outputEvents: Event[]; 34 | blockHeight: bigint; 35 | blockTimestamp: Date; 36 | } 37 | 38 | export async function encodeRunQueryRequest(req: RunQueryRequest, signer: Signer): Promise { 39 | // validate 40 | if (req.protocolVersion != 1) { 41 | throw new Error(`expected ProtocolVersion 1, ${req.protocolVersion} given`); 42 | } 43 | // encode method arguments 44 | const inputArgumentArray = packedArgumentsEncode(req.inputArguments); 45 | 46 | // encode network type 47 | const networkType = networkTypeEncode(req.networkType); 48 | 49 | // encode request 50 | const res = new Client.RunQueryRequestBuilder({ 51 | signedQuery: new Protocol.SignedQueryBuilder({ 52 | query: new Protocol.QueryBuilder({ 53 | protocolVersion: req.protocolVersion, 54 | virtualChainId: req.virtualChainId, 55 | timestamp: Protocol.dateToUnixNano(req.timestamp, 0), 56 | signer: new Protocol.SignerBuilder({ 57 | scheme: 0, 58 | eddsa: new Protocol.EdDSA01SignerBuilder({ 59 | networkType: networkType, 60 | signerPublicKey: await signer.getPublicKey(), 61 | }), 62 | }), 63 | contractName: req.contractName, 64 | methodName: req.methodName, 65 | inputArgumentArray: inputArgumentArray, 66 | }), 67 | signature: null, 68 | }), 69 | }); 70 | 71 | // return 72 | return res.build(); 73 | } 74 | 75 | export function decodeRunQueryResponse(buf: Uint8Array): RunQueryResponse { 76 | // decode response 77 | const runQueryResponseMsg = new InternalMessage(buf, buf.byteLength, Client.RunQueryResponse_Scheme, []); 78 | if (!runQueryResponseMsg.isValid()) { 79 | throw new Error(`response is corrupt and cannot be decoded`); 80 | } 81 | 82 | // decode request status 83 | const requestResultBuf = runQueryResponseMsg.getMessage(0); 84 | const requestResultMsg = new InternalMessage(requestResultBuf, requestResultBuf.byteLength, Client.RequestResult_Scheme, []); 85 | const requestStatus = requestStatusDecode(requestResultMsg.getUint16(0)); 86 | 87 | // decode execution result 88 | const queryResultBuf = runQueryResponseMsg.getMessage(1); 89 | const queryResultMsg = new InternalMessage(queryResultBuf, queryResultBuf.byteLength, Protocol.QueryResult_Scheme, []); 90 | let executionResult = ExecutionResult.EXECUTION_RESULT_NOT_EXECUTED; 91 | if (queryResultBuf.byteLength > 0) { 92 | executionResult = executionResultDecode(queryResultMsg.getUint16(0)); 93 | } 94 | 95 | // decode method arguments 96 | const outputArgumentArray = packedArgumentsDecode(queryResultMsg.rawBufferWithHeaderForField(1, 0)); 97 | 98 | // decode events 99 | const outputEventArray = packedEventsDecode(queryResultMsg.rawBufferWithHeaderForField(2, 0)); 100 | 101 | // return 102 | return { 103 | requestStatus: requestStatus, 104 | executionResult: executionResult, 105 | outputArguments: outputArgumentArray, 106 | outputEvents: outputEventArray, 107 | blockHeight: requestResultMsg.getUint64(1), 108 | blockTimestamp: Protocol.unixNanoToDate(requestResultMsg.getUint64(2)), 109 | }; 110 | } 111 | -------------------------------------------------------------------------------- /src/codec/OpSendTransaction.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import { NetworkType, networkTypeEncode } from "./NetworkType"; 10 | import * as Client from "../protocol/Client"; 11 | import * as Protocol from "../protocol/Protocol"; 12 | import * as Keys from "../crypto/Keys"; 13 | import * as Digest from "../crypto/Digest"; 14 | import { InternalMessage } from "membuffers"; 15 | import { Argument, packedArgumentsDecode, packedArgumentsEncode } from "./Arguments"; 16 | import { Event, packedEventsDecode } from "./Events"; 17 | import { RequestStatus, requestStatusDecode } from "./RequestStatus"; 18 | import { ExecutionResult, executionResultDecode } from "./ExecutionResult"; 19 | import { TransactionStatus, transactionStatusDecode } from "./TransactionStatus"; 20 | import { Signer, ED25519_SIGNATURE_SIZE_BYTES } from "../crypto/Signer"; 21 | 22 | export interface SendTransactionRequest { 23 | protocolVersion: number; 24 | virtualChainId: number; 25 | timestamp: Date; 26 | nanoNonce: number; // nanoseconds in range 0 - 499,999 (that will still round down to 0 in milliseconds) 27 | networkType: NetworkType; 28 | contractName: string; 29 | methodName: string; 30 | inputArguments: Argument[]; 31 | } 32 | 33 | export interface SendTransactionResponse { 34 | requestStatus: RequestStatus; 35 | txHash: Uint8Array; 36 | executionResult: ExecutionResult; 37 | outputArguments: Argument[]; 38 | outputEvents: Event[]; 39 | transactionStatus: TransactionStatus; 40 | blockHeight: bigint; 41 | blockTimestamp: Date; 42 | } 43 | 44 | export async function encodeSendTransactionRequest(req: SendTransactionRequest, signer: Signer): Promise<[Uint8Array, Uint8Array]> { 45 | // validate 46 | if (req.protocolVersion != 1) { 47 | throw new Error(`expected ProtocolVersion 1, ${req.protocolVersion} given`); 48 | } 49 | 50 | // encode method arguments 51 | const inputArgumentArray = packedArgumentsEncode(req.inputArguments); 52 | 53 | // encode network type 54 | const networkType = networkTypeEncode(req.networkType); 55 | 56 | // encode timestamp 57 | const timestampNano = Protocol.dateToUnixNano(req.timestamp, req.nanoNonce); 58 | 59 | // encode request 60 | const res = new Client.SendTransactionRequestBuilder({ 61 | signedTransaction: new Protocol.SignedTransactionBuilder({ 62 | transaction: new Protocol.TransactionBuilder({ 63 | protocolVersion: req.protocolVersion, 64 | virtualChainId: req.virtualChainId, 65 | timestamp: timestampNano, 66 | signer: new Protocol.SignerBuilder({ 67 | scheme: 0, 68 | eddsa: new Protocol.EdDSA01SignerBuilder({ 69 | networkType: networkType, 70 | signerPublicKey: await signer.getPublicKey(), 71 | }), 72 | }), 73 | contractName: req.contractName, 74 | methodName: req.methodName, 75 | inputArgumentArray: inputArgumentArray, 76 | }), 77 | signature: new Uint8Array(ED25519_SIGNATURE_SIZE_BYTES), 78 | }), 79 | }); 80 | 81 | // read encoded bytes 82 | const buf = res.build(); 83 | const sendTransactionRequestMsg = new InternalMessage(buf, buf.byteLength, Client.SendTransactionRequest_Scheme, []); 84 | const signedTransactionBuf = sendTransactionRequestMsg.getMessage(0); 85 | const signedTransactionMsg = new InternalMessage(signedTransactionBuf, signedTransactionBuf.byteLength, Protocol.SignedTransaction_Scheme, []); 86 | const transactionBuf = signedTransactionMsg.rawBufferForField(0, 0); 87 | 88 | // sign 89 | const txHash = Digest.calcTxHash(transactionBuf); 90 | const sig = await signer.signEd25519(txHash); 91 | signedTransactionMsg.setBytes(1, sig); 92 | 93 | // return 94 | return [buf, Digest.generateTxId(txHash, timestampNano)]; 95 | } 96 | 97 | export function decodeSendTransactionResponse(buf: Uint8Array): SendTransactionResponse { 98 | // decode response 99 | const sendTransactionResponseMsg = new InternalMessage(buf, buf.byteLength, Client.SendTransactionResponse_Scheme, []); 100 | if (!sendTransactionResponseMsg.isValid()) { 101 | throw new Error(`response is corrupt and cannot be decoded`); 102 | } 103 | 104 | // decode request status 105 | const requestResultBuf = sendTransactionResponseMsg.getMessage(0); 106 | const requestResultMsg = new InternalMessage(requestResultBuf, requestResultBuf.byteLength, Client.RequestResult_Scheme, []); 107 | const requestStatus = requestStatusDecode(requestResultMsg.getUint16(0)); 108 | 109 | // decode execution result 110 | const transactionReceiptBuf = sendTransactionResponseMsg.getMessage(2); 111 | const transactionReceiptMsg = new InternalMessage(transactionReceiptBuf, transactionReceiptBuf.byteLength, Protocol.TransactionReceipt_Scheme, []); 112 | let executionResult = ExecutionResult.EXECUTION_RESULT_NOT_EXECUTED; 113 | if (transactionReceiptBuf.byteLength > 0) { 114 | executionResult = executionResultDecode(transactionReceiptMsg.getUint16(1)); 115 | } 116 | 117 | // decode method arguments 118 | const outputArgumentArray = packedArgumentsDecode(transactionReceiptMsg.rawBufferWithHeaderForField(2, 0)); 119 | 120 | // decode events 121 | const outputEventArray = packedEventsDecode(transactionReceiptMsg.rawBufferWithHeaderForField(3, 0)); 122 | 123 | // decode transaction status 124 | const transactionStatus = transactionStatusDecode(sendTransactionResponseMsg.getUint16(1)); 125 | 126 | // return 127 | return { 128 | requestStatus: requestStatus, 129 | txHash: transactionReceiptMsg.getBytes(0), 130 | executionResult: executionResult, 131 | outputArguments: outputArgumentArray, 132 | outputEvents: outputEventArray, 133 | transactionStatus: transactionStatus, 134 | blockHeight: requestResultMsg.getUint64(1), 135 | blockTimestamp: Protocol.unixNanoToDate(requestResultMsg.getUint64(2)), 136 | }; 137 | } 138 | -------------------------------------------------------------------------------- /src/codec/RequestStatus.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | export enum RequestStatus { 10 | REQUEST_STATUS_COMPLETED = "COMPLETED", 11 | REQUEST_STATUS_IN_PROCESS = "IN_PROCESS", 12 | REQUEST_STATUS_BAD_REQUEST = "BAD_REQUEST", 13 | REQUEST_STATUS_CONGESTION = "CONGESTION", 14 | REQUEST_STATUS_SYSTEM_ERROR = "SYSTEM_ERROR", 15 | REQUEST_STATUS_OUT_OF_SYNC = "OUT_OF_SYNC", 16 | REQUEST_STATUS_NOT_FOUND = "NOT_FOUND", 17 | } 18 | 19 | export function requestStatusDecode(requestStatus: number): RequestStatus { 20 | switch (requestStatus) { 21 | case 0: 22 | throw new Error(`reserved RequestStatus received`); 23 | case 1: 24 | return RequestStatus.REQUEST_STATUS_COMPLETED; 25 | case 2: 26 | return RequestStatus.REQUEST_STATUS_IN_PROCESS; 27 | case 3: 28 | return RequestStatus.REQUEST_STATUS_BAD_REQUEST; 29 | case 4: 30 | return RequestStatus.REQUEST_STATUS_CONGESTION; 31 | case 5: 32 | return RequestStatus.REQUEST_STATUS_SYSTEM_ERROR; 33 | case 6: 34 | return RequestStatus.REQUEST_STATUS_OUT_OF_SYNC; 35 | case 7: 36 | return RequestStatus.REQUEST_STATUS_NOT_FOUND; 37 | default: 38 | throw new Error(`unsupported RequestStatus received: ${requestStatus}`); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/codec/TransactionStatus.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | export enum TransactionStatus { 10 | TRANSACTION_STATUS_COMMITTED = "COMMITTED", 11 | TRANSACTION_STATUS_DUPLICATE_TRANSACTION_ALREADY_COMMITTED = "DUPLICATE_TRANSACTION_ALREADY_COMMITTED", 12 | TRANSACTION_STATUS_PENDING = "PENDING", 13 | TRANSACTION_STATUS_DUPLICATE_TRANSACTION_ALREADY_PENDING = "DUPLICATE_TRANSACTION_ALREADY_PENDING", 14 | TRANSACTION_STATUS_NO_RECORD_FOUND = "NO_RECORD_FOUND", 15 | TRANSACTION_STATUS_REJECTED_UNSUPPORTED_VERSION = "REJECTED_UNSUPPORTED_VERSION", 16 | TRANSACTION_STATUS_REJECTED_VIRTUAL_CHAIN_MISMATCH = "REJECTED_VIRTUAL_CHAIN_MISMATCH", 17 | TRANSACTION_STATUS_REJECTED_TIMESTAMP_WINDOW_EXCEEDED = "REJECTED_TIMESTAMP_WINDOW_EXCEEDED", 18 | TRANSACTION_STATUS_REJECTED_SIGNATURE_MISMATCH = "REJECTED_SIGNATURE_MISMATCH", 19 | TRANSACTION_STATUS_REJECTED_UNKNOWN_SIGNER_SCHEME = "REJECTED_UNKNOWN_SIGNER_SCHEME", 20 | TRANSACTION_STATUS_REJECTED_GLOBAL_PRE_ORDER = "REJECTED_GLOBAL_PRE_ORDER", 21 | TRANSACTION_STATUS_REJECTED_VIRTUAL_CHAIN_PRE_ORDER = "REJECTED_VIRTUAL_CHAIN_PRE_ORDER", 22 | TRANSACTION_STATUS_REJECTED_SMART_CONTRACT_PRE_ORDER = "REJECTED_SMART_CONTRACT_PRE_ORDER", 23 | TRANSACTION_STATUS_REJECTED_TIMESTAMP_AHEAD_OF_NODE_TIME = "REJECTED_TIMESTAMP_AHEAD_OF_NODE_TIME", 24 | TRANSACTION_STATUS_REJECTED_CONGESTION = "REJECTED_CONGESTION", 25 | TRANSACTION_STATUS_REJECTED_NODE_OUT_OF_SYNC = "REJECTED_NODE_OUT_OF_SYNC", 26 | } 27 | 28 | export function transactionStatusDecode(transactionStatus: number): TransactionStatus { 29 | switch (transactionStatus) { 30 | case 0: 31 | throw new Error(`reserved TransactionStatus received`); 32 | case 1: 33 | return TransactionStatus.TRANSACTION_STATUS_COMMITTED; 34 | case 2: 35 | return TransactionStatus.TRANSACTION_STATUS_DUPLICATE_TRANSACTION_ALREADY_COMMITTED; 36 | case 3: 37 | return TransactionStatus.TRANSACTION_STATUS_PENDING; 38 | case 4: 39 | return TransactionStatus.TRANSACTION_STATUS_DUPLICATE_TRANSACTION_ALREADY_PENDING; 40 | case 6: 41 | return TransactionStatus.TRANSACTION_STATUS_NO_RECORD_FOUND; 42 | case 7: 43 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_UNSUPPORTED_VERSION; 44 | case 8: 45 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_VIRTUAL_CHAIN_MISMATCH; 46 | case 9: 47 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_TIMESTAMP_WINDOW_EXCEEDED; 48 | case 10: 49 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_SIGNATURE_MISMATCH; 50 | case 11: 51 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_UNKNOWN_SIGNER_SCHEME; 52 | case 12: 53 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_GLOBAL_PRE_ORDER; 54 | case 13: 55 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_VIRTUAL_CHAIN_PRE_ORDER; 56 | case 14: 57 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_SMART_CONTRACT_PRE_ORDER; 58 | case 15: 59 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_TIMESTAMP_AHEAD_OF_NODE_TIME; 60 | case 16: 61 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_CONGESTION; 62 | case 17: 63 | return TransactionStatus.TRANSACTION_STATUS_REJECTED_NODE_OUT_OF_SYNC; 64 | default: 65 | throw new Error(`unsupported TransactionStatus received: ${transactionStatus}`); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/codec/contract.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import "../matcher-extensions"; 10 | import { Argument, 11 | argUint32, argUint64, argString, argBytes, argBool, argUint256, argBytes20, argBytes32, 12 | argUint32Array, argUint64Array, argStringArray, argBytesArray, argBoolArray, argUint256Array, argBytes20Array, argBytes32Array } from "./Arguments"; 13 | import { Event } from "./Events"; 14 | import { BlockTransaction, decodeGetBlockResponse, encodeGetBlockRequest } from "./OpGetBlock"; 15 | import { decodeGetTransactionReceiptProofResponse, encodeGetTransactionReceiptProofRequest } from "./OpGetTransactionReceiptProof"; 16 | import { decodeGetTransactionStatusResponse, encodeGetTransactionStatusRequest } from "./OpGetTransactionStatus"; 17 | import { decodeRunQueryResponse, encodeRunQueryRequest } from "./OpRunQuery"; 18 | import { decodeSendTransactionResponse, encodeSendTransactionRequest } from "./OpSendTransaction"; 19 | import { LocalSigner } from ".."; 20 | 21 | describe("Codec contract", () => { 22 | let contractInput: any; 23 | let contractOutput: any; 24 | try { 25 | contractInput = require("../../contract/test/codec/input.json"); 26 | contractOutput = require("../../contract/test/codec/output.json"); 27 | } catch (e) { 28 | throw new Error( 29 | `Contract spec input.json and output.json not found in ROOT/contract/test/codec\nThese files are cloned from the reference implementation found at\nhttps://github.com/orbs-network/orbs-client-sdk-go.git during the prepare step of this package`, 30 | ); 31 | } 32 | 33 | for (let index = 0; index < contractInput.length; index++) { 34 | const inputScenario = contractInput[index]; 35 | const outputScenario = contractOutput[index]; 36 | test(`Test Id: ${inputScenario.Test}`, async () => { 37 | // SendTransactionRequest 38 | if (inputScenario.SendTransactionRequest) { 39 | const signer = new LocalSigner({publicKey: jsonUnmarshalBase64Bytes(inputScenario.SendTransactionRequest.PublicKey), privateKey: jsonUnmarshalBase64Bytes(inputScenario.PrivateKey)}); 40 | const req = { 41 | protocolVersion: jsonUnmarshalNumber(inputScenario.SendTransactionRequest.ProtocolVersion), 42 | virtualChainId: jsonUnmarshalNumber(inputScenario.SendTransactionRequest.VirtualChainId), 43 | timestamp: new Date(inputScenario.SendTransactionRequest.Timestamp), 44 | nanoNonce: 0, 45 | networkType: inputScenario.SendTransactionRequest.NetworkType, 46 | contractName: inputScenario.SendTransactionRequest.ContractName, 47 | methodName: inputScenario.SendTransactionRequest.MethodName, 48 | inputArguments: jsonUnmarshalArguments(inputScenario.SendTransactionRequest.InputArguments, inputScenario.SendTransactionRequest.InputArgumentsTypes), 49 | }; 50 | const [encoded, txId] = await encodeSendTransactionRequest( 51 | req, signer); 52 | const expected = jsonUnmarshalBase64Bytes(outputScenario.SendTransactionRequest); 53 | expect(encoded).toBeEqualToUint8Array(expected); 54 | const expectedTxId = jsonUnmarshalBase64Bytes(outputScenario.TxId); 55 | expect(txId).toBeEqualToUint8Array(expectedTxId); 56 | return; 57 | } 58 | 59 | // RunQueryRequest 60 | if (inputScenario.RunQueryRequest) { 61 | // we don't have it in the source files but the signer can't be instantiated withouth the key 62 | const stubPrivateKey = "k+kZmGoiR3/aAWeJzKMMuEGhNWUJOHFPhfAACmUHa9TfwGxb4kpnre6As1q08Ue7GjXFX/he2mn0Dvgnvd7Bcw=="; 63 | const signer = new LocalSigner({publicKey: jsonUnmarshalBase64Bytes(inputScenario.RunQueryRequest.PublicKey), privateKey: jsonUnmarshalBase64Bytes(stubPrivateKey)}); 64 | 65 | const encoded = await encodeRunQueryRequest({ 66 | protocolVersion: jsonUnmarshalNumber(inputScenario.RunQueryRequest.ProtocolVersion), 67 | virtualChainId: jsonUnmarshalNumber(inputScenario.RunQueryRequest.VirtualChainId), 68 | timestamp: new Date(inputScenario.RunQueryRequest.Timestamp), 69 | networkType: inputScenario.RunQueryRequest.NetworkType, 70 | contractName: inputScenario.RunQueryRequest.ContractName, 71 | methodName: inputScenario.RunQueryRequest.MethodName, 72 | inputArguments: jsonUnmarshalArguments(inputScenario.RunQueryRequest.InputArguments, inputScenario.RunQueryRequest.InputArgumentsTypes), 73 | }, signer); 74 | const expected = jsonUnmarshalBase64Bytes(outputScenario.RunQueryRequest); 75 | expect(encoded).toBeEqualToUint8Array(expected); 76 | return; 77 | } 78 | 79 | // GetTransactionStatusRequest 80 | if (inputScenario.GetTransactionStatusRequest) { 81 | const encoded = await encodeGetTransactionStatusRequest({ 82 | protocolVersion: jsonUnmarshalNumber(inputScenario.GetTransactionStatusRequest.ProtocolVersion), 83 | virtualChainId: jsonUnmarshalNumber(inputScenario.GetTransactionStatusRequest.VirtualChainId), 84 | txId: jsonUnmarshalBase64Bytes(inputScenario.GetTransactionStatusRequest.TxId), 85 | }); 86 | const expected = jsonUnmarshalBase64Bytes(outputScenario.GetTransactionStatusRequest); 87 | expect(encoded).toBeEqualToUint8Array(expected); 88 | return; 89 | } 90 | 91 | // GetTransactionReceiptProofRequest 92 | if (inputScenario.GetTransactionReceiptProofRequest) { 93 | const encoded = await encodeGetTransactionReceiptProofRequest({ 94 | protocolVersion: jsonUnmarshalNumber(inputScenario.GetTransactionReceiptProofRequest.ProtocolVersion), 95 | virtualChainId: jsonUnmarshalNumber(inputScenario.GetTransactionReceiptProofRequest.VirtualChainId), 96 | txId: jsonUnmarshalBase64Bytes(inputScenario.GetTransactionReceiptProofRequest.TxId), 97 | }); 98 | const expected = jsonUnmarshalBase64Bytes(outputScenario.GetTransactionReceiptProofRequest); 99 | expect(encoded).toBeEqualToUint8Array(expected); 100 | return; 101 | } 102 | 103 | // GetBlockRequest 104 | if (inputScenario.GetBlockRequest) { 105 | const encoded = await encodeGetBlockRequest({ 106 | protocolVersion: jsonUnmarshalNumber(inputScenario.GetBlockRequest.ProtocolVersion), 107 | virtualChainId: jsonUnmarshalNumber(inputScenario.GetBlockRequest.VirtualChainId), 108 | blockHeight: BigInt(inputScenario.GetBlockRequest.BlockHeight), 109 | }); 110 | const expected = jsonUnmarshalBase64Bytes(outputScenario.GetBlockRequest); 111 | expect(encoded).toBeEqualToUint8Array(expected); 112 | return; 113 | } 114 | 115 | // SendTransactionResponse 116 | if (inputScenario.SendTransactionResponse) { 117 | const decoded = decodeSendTransactionResponse(jsonUnmarshalBase64Bytes(inputScenario.SendTransactionResponse)); 118 | const [args, argsTypes] = jsonMarshalArguments(decoded.outputArguments); 119 | const res = { 120 | BlockHeight: decoded.blockHeight.toString(), 121 | OutputArguments: args, 122 | OutputArgumentsTypes: argsTypes, 123 | OutputEvents: jsonMarshalEvents(decoded.outputEvents), 124 | RequestStatus: decoded.requestStatus, 125 | ExecutionResult: decoded.executionResult, 126 | BlockTimestamp: decoded.blockTimestamp.toISOString(), 127 | TxHash: jsonMarshalBase64Bytes(decoded.txHash), 128 | TransactionStatus: decoded.transactionStatus, 129 | }; 130 | const expected = outputScenario.SendTransactionResponse; 131 | expect(res).toEqual(expected); 132 | return; 133 | } 134 | 135 | // RunQueryResponse 136 | if (inputScenario.RunQueryResponse) { 137 | const decoded = decodeRunQueryResponse(jsonUnmarshalBase64Bytes(inputScenario.RunQueryResponse)); 138 | const [args, argsTypes] = jsonMarshalArguments(decoded.outputArguments); 139 | const res = { 140 | BlockHeight: decoded.blockHeight.toString(), 141 | OutputArguments: args, 142 | OutputArgumentsTypes: argsTypes, 143 | OutputEvents: jsonMarshalEvents(decoded.outputEvents), 144 | RequestStatus: decoded.requestStatus, 145 | ExecutionResult: decoded.executionResult, 146 | BlockTimestamp: decoded.blockTimestamp.toISOString(), 147 | }; 148 | const expected = outputScenario.RunQueryResponse; 149 | expect(res).toEqual(expected); 150 | return; 151 | } 152 | 153 | // GetTransactionStatusResponse 154 | if (inputScenario.GetTransactionStatusResponse) { 155 | const decoded = decodeGetTransactionStatusResponse(jsonUnmarshalBase64Bytes(inputScenario.GetTransactionStatusResponse)); 156 | const [args, argsTypes] = jsonMarshalArguments(decoded.outputArguments); 157 | const res = { 158 | BlockHeight: decoded.blockHeight.toString(), 159 | OutputArguments: args, 160 | OutputArgumentsTypes: argsTypes, 161 | OutputEvents: jsonMarshalEvents(decoded.outputEvents), 162 | RequestStatus: decoded.requestStatus, 163 | ExecutionResult: decoded.executionResult, 164 | BlockTimestamp: decoded.blockTimestamp.toISOString(), 165 | TxHash: jsonMarshalBase64Bytes(decoded.txHash), 166 | TransactionStatus: decoded.transactionStatus, 167 | }; 168 | const expected = outputScenario.GetTransactionStatusResponse; 169 | expect(res).toEqual(expected); 170 | return; 171 | } 172 | 173 | // GetTransactionReceiptProofResponse 174 | if (inputScenario.GetTransactionReceiptProofResponse) { 175 | const decoded = decodeGetTransactionReceiptProofResponse(jsonUnmarshalBase64Bytes(inputScenario.GetTransactionReceiptProofResponse)); 176 | const [args, argsTypes] = jsonMarshalArguments(decoded.outputArguments); 177 | const res = { 178 | BlockHeight: decoded.blockHeight.toString(), 179 | OutputArguments: args, 180 | OutputArgumentsTypes: argsTypes, 181 | OutputEvents: jsonMarshalEvents(decoded.outputEvents), 182 | RequestStatus: decoded.requestStatus, 183 | ExecutionResult: decoded.executionResult, 184 | BlockTimestamp: decoded.blockTimestamp.toISOString(), 185 | TxHash: jsonMarshalBase64Bytes(decoded.txHash), 186 | TransactionStatus: decoded.transactionStatus, 187 | PackedProof: jsonMarshalBase64Bytes(decoded.packedProof), 188 | PackedReceipt: jsonMarshalBase64Bytes(decoded.packedReceipt), 189 | }; 190 | const expected = outputScenario.GetTransactionReceiptProofResponse; 191 | expect(res).toEqual(expected); 192 | return; 193 | } 194 | 195 | // GetBlockResponse 196 | if (inputScenario.GetBlockResponse) { 197 | const decoded = decodeGetBlockResponse(jsonUnmarshalBase64Bytes(inputScenario.GetBlockResponse)); 198 | const res = { 199 | BlockHeight: decoded.blockHeight.toString(), 200 | BlockTimestamp: decoded.blockTimestamp.toISOString(), 201 | RequestStatus: decoded.requestStatus, 202 | TransactionsBlockHash: jsonMarshalBase64Bytes(decoded.transactionsBlockHash), 203 | TransactionsBlockHeader: { 204 | ProtocolVersion: decoded.transactionsBlockHeader.protocolVersion.toString(), 205 | VirtualChainId: decoded.transactionsBlockHeader.virtualChainId.toString(), 206 | BlockHeight: decoded.transactionsBlockHeader.blockHeight.toString(), 207 | Timestamp: decoded.transactionsBlockHeader.timestamp.toISOString(), 208 | NumTransactions: decoded.transactionsBlockHeader.numTransactions.toString(), 209 | PrevBlockHash: jsonMarshalBase64Bytes(decoded.transactionsBlockHeader.prevBlockHash), 210 | ReferenceTime: decoded.transactionsBlockHeader.referenceTime, 211 | BlockProposerAddress: jsonMarshalBase64Bytes(decoded.transactionsBlockHeader.blockProposerAddress) 212 | }, 213 | ResultsBlockHash: jsonMarshalBase64Bytes(decoded.resultsBlockHash), 214 | ResultsBlockHeader: { 215 | ProtocolVersion: decoded.resultsBlockHeader.protocolVersion.toString(), 216 | VirtualChainId: decoded.resultsBlockHeader.virtualChainId.toString(), 217 | BlockHeight: decoded.resultsBlockHeader.blockHeight.toString(), 218 | Timestamp: decoded.resultsBlockHeader.timestamp.toISOString(), 219 | NumTransactionReceipts: decoded.resultsBlockHeader.numTransactionReceipts.toString(), 220 | PrevBlockHash: jsonMarshalBase64Bytes(decoded.resultsBlockHeader.prevBlockHash), 221 | TransactionsBlockHash: jsonMarshalBase64Bytes(decoded.resultsBlockHeader.transactionsBlockHash), 222 | ReferenceTime: decoded.resultsBlockHeader.referenceTime, 223 | BlockProposerAddress: jsonMarshalBase64Bytes(decoded.resultsBlockHeader.blockProposerAddress) 224 | }, 225 | Transactions: jsonMarshalBlockTransactions(decoded.transactions), 226 | }; 227 | const expected = outputScenario.GetBlockResponse; 228 | expect(res).toEqual(expected); 229 | return; 230 | } 231 | 232 | fail(`unhandled input scenario:\n${JSON.stringify(inputScenario)}`); 233 | }); 234 | } 235 | }); 236 | 237 | function jsonUnmarshalNumber(str: string): number { 238 | return parseInt(str, 10); 239 | } 240 | 241 | function jsonUnmarshalBase64Bytes(str: string): Uint8Array { 242 | const buffer = Buffer.from(str, "base64"); 243 | return new Uint8Array(buffer); 244 | } 245 | 246 | function jsonMarshalBase64Bytes(buf: Uint8Array): string { 247 | return Buffer.from(buf).toString("base64"); 248 | } 249 | 250 | function jsonUnmarshalHexBytes(str: string): Uint8Array { 251 | const buffer = Buffer.from(str, "hex"); 252 | return new Uint8Array(buffer); 253 | } 254 | 255 | function jsonMarshalHexBytes(buf: Uint8Array): string { 256 | return Buffer.from(buf).toString("hex"); 257 | } 258 | 259 | function jsonUnmarshalBigInt(hexValue: string): bigint { 260 | if (hexValue.substring(0, 2) !== "0x") { 261 | hexValue = "0x" + hexValue; 262 | } 263 | return BigInt(hexValue); 264 | } 265 | 266 | function jsonMarshalBigInt(v: bigint): string { 267 | let hex = v.toString(16); 268 | if (hex.length % 2 !== 0) { 269 | hex = "0" + hex; 270 | } 271 | while (hex.length < 64) { 272 | hex = "00" + hex; 273 | } 274 | return hex; 275 | } 276 | 277 | function jsonUnmarshalArguments(args: string[], argTypes: string[]): Argument[] { 278 | const res: Argument[] = []; 279 | if (args.length != argTypes.length) { 280 | throw new Error(`number of args ${args.length} is different than number of argTypes ${argTypes.length}`); 281 | } 282 | for (let i = 0; i < args.length; i++) { 283 | const arg = args[i]; 284 | const argType = argTypes[i]; 285 | switch (argType) { 286 | case "uint32": 287 | res.push(argUint32(jsonUnmarshalNumber(arg))); 288 | break; 289 | case "uint64": 290 | res.push(argUint64(BigInt(arg))); 291 | break; 292 | case "string": 293 | res.push(argString(arg)); 294 | break; 295 | case "bytes": 296 | res.push(argBytes(jsonUnmarshalHexBytes(arg))); 297 | break; 298 | case "bool": 299 | res.push(argBool(arg === "1")); 300 | break; 301 | case "uint256": 302 | res.push(argUint256(jsonUnmarshalBigInt(arg))); 303 | break; 304 | case "bytes20": 305 | res.push(argBytes20(jsonUnmarshalHexBytes(arg))); 306 | break; 307 | case "bytes32": 308 | res.push(argBytes32(jsonUnmarshalHexBytes(arg))); 309 | break; 310 | case "uint32Array": 311 | let arrUint32 = JSON.parse(arg); 312 | arrUint32 = arrUint32.map(jsonUnmarshalNumber); 313 | res.push(argUint32Array(arrUint32)); 314 | break; 315 | case "uint64Array": 316 | let arrUint64 = JSON.parse(arg); 317 | arrUint64 = arrUint64.map(BigInt); 318 | res.push(argUint64Array(arrUint64)); 319 | break; 320 | case "stringArray": 321 | const arrString = JSON.parse(arg); 322 | res.push(argStringArray(arrString)); 323 | break; 324 | case "bytesArray": 325 | let arrBytes = JSON.parse(arg); 326 | arrBytes = arrBytes.map(jsonUnmarshalHexBytes); 327 | res.push(argBytesArray(arrBytes)); 328 | break; 329 | case "boolArray": 330 | let arrBool = JSON.parse(arg); 331 | arrBool = arrBool.map(function(a: string): boolean { return a === "1"; }); 332 | res.push(argBoolArray(arrBool)); 333 | break; 334 | case "uint256Array": 335 | let arrUint256 = JSON.parse(arg); 336 | arrUint256 = arrUint256.map(jsonUnmarshalBigInt); 337 | res.push(argUint256Array(arrUint256)); 338 | break; 339 | case "bytes20Array": 340 | let arrBytes20 = JSON.parse(arg); 341 | arrBytes20 = arrBytes20.map(jsonUnmarshalHexBytes); 342 | res.push(argBytes20Array(arrBytes20)); 343 | break; 344 | case "bytes32Array": 345 | let arrBytes32 = JSON.parse(arg); 346 | arrBytes32 = arrBytes32.map(jsonUnmarshalHexBytes); 347 | res.push(argBytes32Array(arrBytes32)); 348 | break; 349 | default: 350 | throw new Error(`unknown argType ${argType}`); 351 | } 352 | } 353 | return res; 354 | } 355 | 356 | function jsonMarshalArguments(args: Argument[]): [string[], string[]] { 357 | const res: string[] = []; 358 | const resTypes: string[] = []; 359 | for (let i = 0; i < args.length; i++) { 360 | const arg = args[i]; 361 | switch (arg.type) { 362 | case "uint32": 363 | res.push(arg.value.toString()); 364 | resTypes.push("uint32"); 365 | break; 366 | case "uint64": 367 | res.push(arg.value.toString()); 368 | resTypes.push("uint64"); 369 | break; 370 | case "string": 371 | res.push(arg.value); 372 | resTypes.push("string"); 373 | break; 374 | case "bytes": 375 | res.push(jsonMarshalHexBytes(arg.value)); 376 | resTypes.push("bytes"); 377 | break; 378 | case "bool": 379 | res.push(arg.value ? "1" : "0"); 380 | resTypes.push("bool"); 381 | break; 382 | case "uint256": 383 | res.push(jsonMarshalBigInt(arg.value)); 384 | resTypes.push("uint256"); 385 | break; 386 | case "bytes20": 387 | res.push(jsonMarshalHexBytes(arg.value)); 388 | resTypes.push("bytes20"); 389 | break; 390 | case "bytes32": 391 | res.push(jsonMarshalHexBytes(arg.value)); 392 | resTypes.push("bytes32"); 393 | break; 394 | case "uint32Array": 395 | const arrUint32AsString = arg.value.map(function(a: number): string { return a.toString(); }); 396 | res.push(JSON.stringify(arrUint32AsString)); 397 | resTypes.push("uint32Array"); 398 | break; 399 | case "uint64Array": 400 | const arrUint64AsString = arg.value.map(function(a: bigint): string { return a.toString(); }); 401 | res.push(JSON.stringify(arrUint64AsString)); 402 | resTypes.push("uint64Array"); 403 | break; 404 | case "stringArray": 405 | res.push(JSON.stringify(arg.value)); 406 | resTypes.push("stringArray"); 407 | break; 408 | case "bytesArray": 409 | const arrBytesAsStrings = arg.value.map(jsonMarshalHexBytes); 410 | res.push(JSON.stringify(arrBytesAsStrings)); 411 | resTypes.push("bytesArray"); 412 | break; 413 | case "boolArray": 414 | const arrBoolAsString = arg.value.map(function(a: boolean): string { return a ? "1" : "0"; }); 415 | res.push(JSON.stringify(arrBoolAsString)); 416 | resTypes.push("boolArray"); 417 | break; 418 | case "uint256Array": 419 | const arrUint256AsStrings = arg.value.map(jsonMarshalBigInt); 420 | res.push(JSON.stringify(arrUint256AsStrings)); 421 | resTypes.push("uint256Array"); 422 | break; 423 | case "bytes20Array": 424 | const arrBytes20AsStrings = arg.value.map(jsonMarshalHexBytes); 425 | res.push(JSON.stringify(arrBytes20AsStrings)); 426 | resTypes.push("bytes20Array"); 427 | break; 428 | case "bytes32Array": 429 | const arrBytes32AsStrings = arg.value.map(jsonMarshalHexBytes); 430 | res.push(JSON.stringify(arrBytes32AsStrings)); 431 | resTypes.push("bytes32Array"); 432 | break; 433 | default: 434 | throw new Error(`unsupported type in json marshal of method arguments`); 435 | } 436 | } 437 | return [res, resTypes]; 438 | } 439 | 440 | interface MarshaledEvent { 441 | ContractName: string; 442 | EventName: string; 443 | Arguments: string[]; 444 | ArgumentsTypes: string[]; 445 | } 446 | 447 | function jsonMarshalEvents(events: Event[]): MarshaledEvent[] { 448 | const res: MarshaledEvent[] = []; 449 | for (let i = 0; i < events.length; i++) { 450 | const event = events[i]; 451 | const [args, argsTypes] = jsonMarshalArguments(event.arguments); 452 | res.push({ 453 | ContractName: event.contractName, 454 | EventName: event.eventName, 455 | Arguments: args, 456 | ArgumentsTypes: argsTypes, 457 | }); 458 | } 459 | return res; 460 | } 461 | 462 | interface MarshaledBlockTransaction { 463 | ProtocolVersion: string; 464 | VirtualChainId: string; 465 | Timestamp: string; 466 | InputArguments: string[]; 467 | InputArgumentsTypes: string[]; 468 | OutputArguments: string[]; 469 | OutputArgumentsTypes: string[]; 470 | OutputEvents: MarshaledEvent[]; 471 | TxId: string; 472 | TxHash: string; 473 | SignerPublicKey: string; 474 | ContractName: string; 475 | MethodName: string; 476 | ExecutionResult: string; 477 | } 478 | 479 | function jsonMarshalBlockTransactions(transactions: BlockTransaction[]): MarshaledBlockTransaction[] { 480 | const res: MarshaledBlockTransaction[] = []; 481 | for (let i = 0; i < transactions.length; i++) { 482 | const transaction = transactions[i]; 483 | const [inArgs, inArgsTypes] = jsonMarshalArguments(transaction.inputArguments); 484 | const [outArgs, outArgsTypes] = jsonMarshalArguments(transaction.outputArguments); 485 | res.push({ 486 | ProtocolVersion: transaction.protocolVersion.toString(), 487 | VirtualChainId: transaction.virtualChainId.toString(), 488 | Timestamp: transaction.timestamp.toISOString(), 489 | InputArguments: inArgs, 490 | InputArgumentsTypes: inArgsTypes, 491 | OutputArguments: outArgs, 492 | OutputArgumentsTypes: outArgsTypes, 493 | OutputEvents: jsonMarshalEvents(transaction.outputEvents), 494 | TxId: jsonMarshalBase64Bytes(transaction.txId), 495 | TxHash: jsonMarshalBase64Bytes(transaction.txHash), 496 | SignerPublicKey: jsonMarshalBase64Bytes(transaction.signerPublicKey), 497 | ContractName: transaction.contractName, 498 | MethodName: transaction.methodName, 499 | ExecutionResult: transaction.executionResult, 500 | }); 501 | } 502 | return res; 503 | } 504 | -------------------------------------------------------------------------------- /src/crypto/Digest.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import * as Digest from "./Digest"; 10 | import { encodeHex } from "./Encoding"; 11 | 12 | test("HexEncodeWithChecksum", () => { 13 | expect(() => { Digest.contractNameToAddressAsBytes(""); }).toThrowError("invalid contract name"); 14 | 15 | // This value was generated by orbs-contract-sdk-go which was tested with an e2e test against gamma 16 | expect(encodeHex(Digest.contractNameToAddressAsBytes("ERC721Receiver1567581564581813000"))).toEqual("0x63D2fE13c426Fe78E3C92E0B22d04508c54aA4BF"); 17 | }); -------------------------------------------------------------------------------- /src/crypto/Digest.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import * as Hash from "./Hash"; 10 | import { calcSha256, SHA256_HASH_SIZE_BYTES } from "./Hash"; 11 | import { ED25519_PUBLIC_KEY_SIZE_BYTES } from "./Keys"; 12 | import { getTextEncoder, DataViewWrapper } from "membuffers"; 13 | 14 | export const CLIENT_ADDRESS_SIZE_BYTES = 20; 15 | export const CLIENT_ADDRESS_SHA256_OFFSET = SHA256_HASH_SIZE_BYTES - CLIENT_ADDRESS_SIZE_BYTES; 16 | 17 | export const TX_ID_SIZE_BYTES = 8 + 32; 18 | 19 | export function calcClientAddressOfEd25519PublicKey(publicKey: Uint8Array): Uint8Array { 20 | if (publicKey.byteLength != ED25519_PUBLIC_KEY_SIZE_BYTES) { 21 | throw new Error(`public key has invalid length ${publicKey.byteLength}`); 22 | } 23 | return calcSha256(publicKey).slice(CLIENT_ADDRESS_SHA256_OFFSET); 24 | } 25 | 26 | export function calcTxHash(transactionBuf: Uint8Array): Uint8Array { 27 | return Hash.calcSha256(transactionBuf); 28 | } 29 | 30 | export function generateTxId(txHash: Uint8Array, txTimestamp: bigint): Uint8Array { 31 | const res = new Uint8Array(TX_ID_SIZE_BYTES); 32 | const dataView = new DataViewWrapper(res.buffer, res.byteOffset); 33 | dataView.setBigUint64(0, txTimestamp, true); 34 | res.set(txHash, 8); 35 | return res; 36 | } 37 | 38 | export function extractTxId(txId: Uint8Array): [Uint8Array, bigint] { 39 | if (txId.byteLength != TX_ID_SIZE_BYTES) { 40 | throw new Error(`txid has invalid length ${txId.byteLength}`); 41 | } 42 | const dataView = new DataViewWrapper(txId.buffer, txId.byteOffset); 43 | const txTimestamp = dataView.getBigUint64(0, true); 44 | const txHash = txId.subarray(8); 45 | return [txHash, txTimestamp]; 46 | } 47 | 48 | export function calcQueryHash(queryBuf: Uint8Array): Uint8Array { 49 | return Hash.calcSha256(queryBuf); 50 | } 51 | 52 | export function contractNameToAddressAsBytes(contractName: string): Uint8Array { 53 | if (!contractName || contractName === "") { 54 | throw new Error("invalid contract name"); 55 | } 56 | 57 | return calcSha256(getTextEncoder().encode(contractName)).slice(CLIENT_ADDRESS_SHA256_OFFSET); 58 | } 59 | -------------------------------------------------------------------------------- /src/crypto/Encoding.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import "../matcher-extensions"; 10 | import * as Encoding from "./Encoding"; 11 | 12 | const encodeStringTestTable = [ 13 | { sourceHex: "de709f2102306220921060314715629080e2fb77", checksumEncodedHex: "0xdE709f2102306220921060314715629080e2FB77" }, 14 | { sourceHex: "dbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", checksumEncodedHex: "0xdBf03B407c01e7CD3CBea99509d93F8DDdc8c6Fb" }, 15 | { sourceHex: "abcdef", checksumEncodedHex: "0xABcDEf" }, 16 | { sourceHex: "dbF03B407c01E7cD3CBea99509d93f8DDDC8C6FBdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB", checksumEncodedHex: "0xDBF03b407C01E7CD3CBea99509D93F8DdDC8C6FBdbF03b407C01e7Cd3cbEa99509D93f8DdDc8C6FB" }, 17 | { 18 | sourceHex: 19 | "dbF03B407c01E7cD3CBea99509d93f8DDDC8C6FBdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FBde709f2102306220921060314715629080e2fb77dbF03B407c01E7cD3CBea99509d93f8DDDC8C6FBdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FBde709f2102306220921060314715629080e2fb77", 20 | checksumEncodedHex: 21 | "0xDBf03b407C01E7Cd3CBeA99509d93F8DDdC8C6fBDBf03B407c01E7CD3cbEa99509d93f8dDDc8C6FbdE709f2102306220921060314715629080E2FB77dbf03b407C01E7Cd3CbEA99509D93f8Dddc8c6fBDbF03B407C01E7cd3cBeA99509d93f8DDDc8C6FbDE709F2102306220921060314715629080e2FB77", 22 | }, 23 | ]; 24 | 25 | test("HexEncodeWithChecksum", () => { 26 | for (const pair of encodeStringTestTable) { 27 | const data = Buffer.from(pair.sourceHex, "hex"); 28 | const encoded = Encoding.encodeHex(data); 29 | expect(encoded).toBe(pair.checksumEncodedHex); 30 | } 31 | }); 32 | 33 | test("HexDecodeGoodChecksum", () => { 34 | for (const pair of encodeStringTestTable) { 35 | const rawData = Buffer.from(pair.sourceHex, "hex"); 36 | const decoded = Encoding.decodeHex(pair.checksumEncodedHex); 37 | expect(decoded).toBeEqualToUint8Array(rawData); 38 | } 39 | }); 40 | 41 | test("HexDecodeBadChecksum", () => { 42 | const pair = encodeStringTestTable[0]; 43 | const rawData = Buffer.from(pair.sourceHex, "hex"); 44 | const wrongCheckSum = "de" + pair.checksumEncodedHex.slice(4); 45 | expect(() => { 46 | const decoded = Encoding.decodeHex(wrongCheckSum); 47 | }).toThrow(); 48 | }); 49 | 50 | test("HexDecodeInvalidHex", () => { 51 | expect(() => { 52 | const decoded = Encoding.decodeHex("0"); 53 | }).toThrow(); 54 | }); 55 | -------------------------------------------------------------------------------- /src/crypto/Encoding.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import * as Hash from "./Hash"; 10 | import { getTextDecoder } from "membuffers"; 11 | 12 | // without 0x 13 | function simpleHexEncodeAsCharCodeArray(data: Uint8Array): Uint8Array { 14 | const res = new Uint8Array(2 * data.byteLength); 15 | for (let i = 0; i < data.byteLength; i++) { 16 | const hex = "00" + data[i].toString(16).toLowerCase(); 17 | res[2 * i] = hex.charCodeAt(hex.length - 2); 18 | res[2 * i + 1] = hex.charCodeAt(hex.length - 1); 19 | } 20 | return res; 21 | } 22 | 23 | // without 0x 24 | function simpleHexDecode(str: string): Uint8Array { 25 | if (str.length % 2 != 0) { 26 | throw new Error(`invalid hex string '${str}'`); 27 | } 28 | const res = new Uint8Array(str.length / 2); 29 | for (let i = 0; i < str.length; i += 2) { 30 | const byte = parseInt(str.substr(i, 2), 16); 31 | if (isNaN(byte)) { 32 | throw new Error(`invalid hex string '${str}'`); 33 | } 34 | res[i / 2] = byte; 35 | } 36 | return res; 37 | } 38 | 39 | export function encodeHex(data: Uint8Array): string { 40 | const result = simpleHexEncodeAsCharCodeArray(data); 41 | const hashed = Hash.calcSha256(data); 42 | 43 | for (let i = 0; i < 2 * data.byteLength; i++) { 44 | const byteIndex = Math.floor(i / 2); 45 | let hashByte = hashed[byteIndex % Hash.SHA256_HASH_SIZE_BYTES]; 46 | if (i % 2 == 0) { 47 | hashByte = hashByte >> 4; 48 | } else { 49 | hashByte &= 0xf; 50 | } 51 | 52 | // 57 = "9" 53 | if (result[i] > 57 && hashByte > 7) { 54 | result[i] -= 32; 55 | } 56 | } 57 | 58 | return "0x" + getTextDecoder().decode(result); 59 | } 60 | 61 | export function decodeHex(str: string): Uint8Array { 62 | if (str.startsWith("0x")) { 63 | str = str.slice(2); 64 | } 65 | 66 | const data = simpleHexDecode(str); 67 | 68 | const encoded = encodeHex(data); 69 | if (encoded.slice(2) != str) { 70 | // checksum error, we will allow if the source is in uniform case (all lower/upper) 71 | if (str.toUpperCase() == str || str.toLowerCase() == str) { 72 | return data; 73 | } else { 74 | throw new Error(`invalid checksum on hex string '${str}'`); 75 | } 76 | } 77 | 78 | return data; 79 | } 80 | -------------------------------------------------------------------------------- /src/crypto/Hash.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import "../matcher-extensions"; 10 | import * as Hash from "./Hash"; 11 | import { getTextEncoder } from "membuffers"; 12 | 13 | const someData = getTextEncoder().encode("testing"); 14 | const ExpectedSha256 = Buffer.from("cf80cd8aed482d5d1527d7dc72fceff84e6326592848447d2dc0b0e87dfc9a90", "hex"); 15 | 16 | test("CalcSha256", () => { 17 | const h = Hash.calcSha256(someData); 18 | expect(h).toBeEqualToUint8Array(ExpectedSha256); 19 | }); 20 | -------------------------------------------------------------------------------- /src/crypto/Hash.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import hash from "hash.js"; 10 | 11 | export const SHA256_HASH_SIZE_BYTES = 32; 12 | 13 | export function calcSha256(data: Uint8Array): Uint8Array { 14 | const inputArr = [].slice.call(data); 15 | const outputArr = hash 16 | .sha256() 17 | .update(inputArr) 18 | .digest(); 19 | return new Uint8Array(outputArr); 20 | } 21 | -------------------------------------------------------------------------------- /src/crypto/Keys.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import "../matcher-extensions"; 10 | import * as Keys from "./Keys"; 11 | 12 | test("GenerateEd25519", () => { 13 | const keyPair1 = Keys.generateEd25519Key(); 14 | console.log("pair1:", Buffer.from(keyPair1.privateKey).toString("hex")); 15 | expect(keyPair1.publicKey.byteLength).toBe(Keys.ED25519_PUBLIC_KEY_SIZE_BYTES); 16 | expect(keyPair1.privateKey.byteLength).toBe(Keys.ED25519_PRIVATE_KEY_SIZE_BYTES); 17 | 18 | const keyPair2 = Keys.generateEd25519Key(); 19 | console.log("pair2:", Buffer.from(keyPair2.privateKey).toString("hex")); 20 | expect(keyPair1.privateKey).not.toBeEqualToUint8Array(keyPair2.privateKey); 21 | }); 22 | -------------------------------------------------------------------------------- /src/crypto/Keys.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import elliptic from "elliptic"; 10 | import getRandomValues from "get-random-values"; 11 | 12 | export const ED25519_PUBLIC_KEY_SIZE_BYTES = 32; 13 | export const ED25519_PRIVATE_KEY_SIZE_BYTES = 64; 14 | 15 | export interface Ed25519KeyPair { 16 | publicKey: Uint8Array; 17 | privateKey: Uint8Array; 18 | } 19 | 20 | export function generateEd25519Key(): Ed25519KeyPair { 21 | // generate secure random 22 | const secureRandom = new Uint8Array(ED25519_PRIVATE_KEY_SIZE_BYTES - ED25519_PUBLIC_KEY_SIZE_BYTES); 23 | getRandomValues(secureRandom); 24 | 25 | // generate key 26 | const ec = new elliptic.eddsa("ed25519"); 27 | const key = ec.keyFromSecret(uint8ArrayToHexString(secureRandom)); 28 | // console.log(key.getPublic("hex")); 29 | // console.log(key.getSecret("hex")); 30 | 31 | // return 32 | const publicKey = new Uint8Array(key.getPublic("bytes")); 33 | const privateKey = new Uint8Array(ED25519_PRIVATE_KEY_SIZE_BYTES); 34 | privateKey.set(new Uint8Array(key.getSecret("bytes")), 0); 35 | privateKey.set(publicKey, ED25519_PRIVATE_KEY_SIZE_BYTES - ED25519_PUBLIC_KEY_SIZE_BYTES); 36 | return { publicKey, privateKey }; 37 | } 38 | 39 | function uint8ArrayToHexString(arr: Uint8Array): string { 40 | return Array.prototype.map.call(arr, (x: any) => ("00" + x.toString(16)).slice(-2)).join(""); 41 | } 42 | -------------------------------------------------------------------------------- /src/crypto/Signer.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import { signEd25519, verifyEd25519 } from "./Signer"; 10 | import { getTextEncoder } from "membuffers"; 11 | 12 | const someDataToSign = getTextEncoder().encode("this is what we want to sign"); 13 | const PublicKey1 = Buffer.from("92d469d7c004cc0b24a192d9457836bf38effa27536627ef60718b00b0f33152", "hex"); 14 | const PrivateKey1 = Buffer.from("3b24b5f9e6b1371c3b5de2e402a96930eeafe52111bb4a1b003e5ecad3fab53892d469d7c004cc0b24a192d9457836bf38effa27536627ef60718b00b0f33152", "hex"); 15 | 16 | test("SignEd25519", () => { 17 | const sig = signEd25519(PrivateKey1, someDataToSign); 18 | expect(verifyEd25519(PublicKey1, someDataToSign, sig)).toBe(true); 19 | 20 | sig[0] += 1; // corrupt the signature 21 | expect(verifyEd25519(PublicKey1, someDataToSign, sig)).toBe(false); 22 | }); 23 | -------------------------------------------------------------------------------- /src/crypto/Signer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import * as Keys from "./Keys"; 10 | import elliptic from "elliptic"; 11 | 12 | export const ED25519_SIGNATURE_SIZE_BYTES = 64; 13 | 14 | export interface Signer { 15 | getPublicKey(): Promise; 16 | signEd25519(data: Uint8Array): Promise; 17 | } 18 | 19 | export class LocalSigner implements Signer { 20 | constructor( 21 | private fields: { 22 | publicKey: Uint8Array; 23 | privateKey: Uint8Array; 24 | } 25 | ) { 26 | if (this.fields.publicKey.byteLength != Keys.ED25519_PUBLIC_KEY_SIZE_BYTES) { 27 | throw new Error(`expected PublicKey length ${Keys.ED25519_PUBLIC_KEY_SIZE_BYTES}, ${this.fields.publicKey.byteLength} given`); 28 | } 29 | 30 | if (this.fields.privateKey.byteLength != Keys.ED25519_PRIVATE_KEY_SIZE_BYTES) { 31 | throw new Error(`expected PublicKey length ${Keys.ED25519_PRIVATE_KEY_SIZE_BYTES}, ${this.fields.privateKey.byteLength} given`); 32 | } 33 | } 34 | 35 | async signEd25519(data: Uint8Array): Promise { 36 | return signEd25519(this.fields.privateKey, data); 37 | } 38 | 39 | async getPublicKey(): Promise { 40 | return this.fields.publicKey; 41 | } 42 | } 43 | 44 | export function signEd25519(privateKey: Uint8Array, data: Uint8Array): Uint8Array { 45 | if (privateKey.byteLength != Keys.ED25519_PRIVATE_KEY_SIZE_BYTES) { 46 | throw new Error(`cannot sign with ed25519, private key invalid with length ${privateKey.byteLength}`); 47 | } 48 | const ec = new elliptic.eddsa("ed25519"); 49 | const privateKeyString = uint8ArrayToHexString(privateKey.subarray(0, Keys.ED25519_PRIVATE_KEY_SIZE_BYTES - Keys.ED25519_PUBLIC_KEY_SIZE_BYTES)); 50 | const key = ec.keyFromSecret(privateKeyString); 51 | // console.log(key.getPublic("hex")); 52 | // console.log(key.getSecret("hex")); 53 | return new Uint8Array(key.sign(data).toBytes()); 54 | } 55 | 56 | export function verifyEd25519(publicKey: Uint8Array, data: Uint8Array, signature: Uint8Array): boolean { 57 | if (publicKey.byteLength != Keys.ED25519_PUBLIC_KEY_SIZE_BYTES) { 58 | throw new Error(`cannot verify with ed25519, public key invalid with length ${publicKey.byteLength}`); 59 | } 60 | const ec = new elliptic.eddsa("ed25519"); 61 | const publicKeyString = uint8ArrayToHexString(publicKey); 62 | const key = ec.keyFromPublic(publicKeyString); 63 | // console.log(key.getPublic("hex")); 64 | // console.log(key.getSecret("hex")); 65 | const signatureBytes = [].slice.call(signature); 66 | return key.verify(data, signatureBytes); 67 | } 68 | 69 | function uint8ArrayToHexString(arr: Uint8Array): string { 70 | return Array.prototype.map.call(arr, (x: any) => ("00" + x.toString(16)).slice(-2)).join(""); 71 | } 72 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | export { createAccount, addressToBytes, bytesToAddress } from "./orbs/Account"; 10 | export { ExecutionResult } from "./codec/ExecutionResult"; 11 | export { RequestStatus } from "./codec/RequestStatus"; 12 | export { Client, PROCESSOR_TYPE_NATIVE, PROCESSOR_TYPE_JAVASCRIPT } from "./orbs/Client"; 13 | export { calcClientAddressOfEd25519PublicKey, contractNameToAddressAsBytes } from "./crypto/Digest"; 14 | export { encodeHex, decodeHex } from "./crypto/Encoding"; 15 | export { argUint32, argUint64, argString, argBytes, argBool, argUint256, argBytes20, argBytes32, 16 | argUint32Array, argUint64Array, argStringArray, argBytesArray, argBoolArray, argUint256Array, argBytes20Array, argBytes32Array, 17 | argAddress } from "./codec/Arguments"; 18 | export { NetworkType } from "./codec/NetworkType"; 19 | export { LocalSigner } from "./crypto/Signer"; 20 | -------------------------------------------------------------------------------- /src/lib.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | export * from "./index"; 10 | export { Argument, ArgUint32, ArgUint64, ArgString, ArgBytes, ArgBool, ArgUint256, ArgBytes20, ArgBytes32, 11 | ArgUint32Array, ArgUint64Array, ArgStringArray, ArgBytesArray, ArgBoolArray, ArgUint256Array, ArgBytes20Array, ArgBytes32Array } from "./codec/Arguments"; 12 | export { Account } from "./orbs/Account"; 13 | export { Signer } from "./crypto/Signer"; 14 | -------------------------------------------------------------------------------- /src/matcher-extensions.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace jest { 2 | interface Matchers { 3 | toBeEqualToUint8Array(expected: Uint8Array): R; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/matcher-extensions.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | function arrayBufferToHex(buff) { 10 | return Array.prototype.map.call(new Uint8Array(buff), x => ('00' + x.toString(16)).slice(-2)).join(''); 11 | } 12 | 13 | function uint8ArrayToHex(arr) { 14 | return Array.prototype.map.call(arr, x => ('00' + x.toString(16)).slice(-2)).join(''); 15 | } 16 | 17 | expect.extend({ 18 | toBeEqualToArrayBuffer(received, other) { 19 | if (received.byteLength != other.byteLength) { 20 | return { 21 | message: () => `expected arrayBuffer length ${received.byteLength} to be equal ${other.byteLength}`, 22 | pass: false, 23 | }; 24 | } 25 | received = new Uint8Array(received); 26 | other = new Uint8Array(other); 27 | for (let i = 0; i < received.byteLength; i++) { 28 | if (received[i] != other[i]) { 29 | return { 30 | message: () => `expected arrayBuffer ${arrayBufferToHex(received)} to equal ${arrayBufferToHex(other)}`, 31 | pass: false, 32 | }; 33 | } 34 | } 35 | return { 36 | message: () => `expected arrayBuffer\n${arrayBufferToHex(received)} not to equal\n${arrayBufferToHex(other)}`, 37 | pass: true, 38 | }; 39 | }, 40 | toBeEqualToUint8Array(received, other) { 41 | if (received.byteLength != other.byteLength) { 42 | return { 43 | message: () => `expected arrayBuffer length ${received.byteLength} to be equal ${other.byteLength}\n${uint8ArrayToHex(received)}\n${uint8ArrayToHex(other)}`, 44 | pass: false, 45 | }; 46 | } 47 | for (let i = 0; i < received.byteLength; i++) { 48 | if (received[i] != other[i]) { 49 | return { 50 | message: () => `expected uint8Array\n${uint8ArrayToHex(received)} to equal\n${uint8ArrayToHex(other)}`, 51 | pass: false, 52 | }; 53 | } 54 | } 55 | return { 56 | message: () => `expected uint8Array ${uint8ArrayToHex(received)} not to equal ${uint8ArrayToHex(other)}`, 57 | pass: true, 58 | }; 59 | }, 60 | }); -------------------------------------------------------------------------------- /src/orbs/Account.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import * as Keys from "../crypto/Keys"; 10 | import * as Digest from "../crypto/Digest"; 11 | import * as Encoding from "../crypto/Encoding"; 12 | 13 | export interface Account { 14 | publicKey: Uint8Array; 15 | privateKey: Uint8Array; 16 | address: string; // hex string starting with 0x 17 | } 18 | 19 | export function createAccount(): Account { 20 | const keyPair = Keys.generateEd25519Key(); 21 | const rawAddress = Digest.calcClientAddressOfEd25519PublicKey(keyPair.publicKey); 22 | return { 23 | publicKey: keyPair.publicKey, 24 | privateKey: keyPair.privateKey, 25 | address: bytesToAddress(rawAddress), 26 | }; 27 | } 28 | 29 | export function addressToBytes(address: string): Uint8Array { 30 | return Encoding.decodeHex(address); 31 | } 32 | 33 | export function bytesToAddress(rawAddress: Uint8Array): string { 34 | return Encoding.encodeHex(rawAddress); 35 | } 36 | -------------------------------------------------------------------------------- /src/orbs/Client.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import { Client } from "./Client"; 10 | import { LocalSigner, NetworkType, createAccount } from ".."; 11 | 12 | test("multiple concurrent createTransaction with identical args have different txids", async () => { 13 | const NUM_TX = 10; 14 | 15 | // generate a bunch of identical transactions at the same time 16 | const client = new Client("http://endpoint.com", 42, NetworkType.NETWORK_TYPE_MAIN_NET, new LocalSigner(createAccount())); 17 | let promises = []; 18 | for (let i = 0; i < NUM_TX ; i++) { 19 | promises.push(client.createTransaction("contract1", "method1", [])); 20 | } 21 | 22 | // extract their tx ids 23 | let txIds = []; 24 | const values = await Promise.all(promises); 25 | for (let i = 0; i < NUM_TX ; i++) { 26 | const [tx, txId] = values[i]; 27 | txIds.push(txId); 28 | } 29 | 30 | // make sure all tx ids are different 31 | for (let i = 0; i < NUM_TX; i++) { 32 | for (let j = i+1; j < NUM_TX; j++) { 33 | expect(txIds[i]).not.toEqual(txIds[j]); 34 | } 35 | } 36 | }); 37 | 38 | test("bumpNanoNonce is always 0 - 499,999", () => { 39 | const client = new Client("http://endpoint.com", 42, NetworkType.NETWORK_TYPE_MAIN_NET, new LocalSigner(createAccount())); 40 | for (let i = 0; i < 2000000; i++) { 41 | const n = client.bumpNanoNonce(); 42 | if (n < 0 || n > 499999) throw new Error(`bumpNanoNonce returned ${n} which is not 0 - 499,999`); 43 | } 44 | }); -------------------------------------------------------------------------------- /src/orbs/Client.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import * as Encoding from "../crypto/Encoding"; 10 | import { NetworkType } from "../codec/NetworkType"; 11 | import { Argument, argString, argUint32, argBytes } from "../codec/Arguments"; 12 | import { decodeSendTransactionResponse, encodeSendTransactionRequest, SendTransactionResponse } from "../codec/OpSendTransaction"; 13 | import { RunQueryResponse, decodeRunQueryResponse, encodeRunQueryRequest } from "../codec/OpRunQuery"; 14 | import { decodeGetTransactionStatusResponse, encodeGetTransactionStatusRequest, GetTransactionStatusResponse } from "../codec/OpGetTransactionStatus"; 15 | import { decodeGetTransactionReceiptProofResponse, encodeGetTransactionReceiptProofRequest, GetTransactionReceiptProofResponse } from "../codec/OpGetTransactionReceiptProof"; 16 | import { decodeGetBlockResponse, encodeGetBlockRequest, GetBlockResponse } from "../codec/OpGetBlock"; 17 | import axios, { AxiosResponse } from "axios"; 18 | import { Signer } from "../crypto/Signer"; 19 | import { getTextDecoder } from "membuffers"; 20 | 21 | const PROTOCOL_VERSION = 1; 22 | const CONTENT_TYPE_MEMBUFFERS = "application/membuffers"; 23 | const SEND_TRANSACTION_URL = "/api/v1/send-transaction"; 24 | const RUN_QUERY_URL = "/api/v1/run-query"; 25 | const GET_TRANSACTION_STATUS_URL = "/api/v1/get-transaction-status"; 26 | const GET_TRANSACTION_RECEIPT_PROOF_URL = "/api/v1/get-transaction-receipt-proof"; 27 | const GET_BLOCK_URL = "/api/v1/get-block"; 28 | 29 | export const PROCESSOR_TYPE_NATIVE = 1; 30 | export const PROCESSOR_TYPE_JAVASCRIPT = 2; 31 | 32 | export class Client { 33 | private nextNanoNonce: number; 34 | 35 | constructor(private endpoint: string, private virtualChainId: number, private networkType: NetworkType, private signer: Signer) { 36 | this.nextNanoNonce = 0; 37 | } 38 | 39 | bumpNanoNonce(): number { 40 | const res = this.nextNanoNonce; 41 | this.nextNanoNonce++; 42 | if (this.nextNanoNonce > 499999) this.nextNanoNonce = 0; 43 | return res; 44 | } 45 | 46 | async createTransaction(contractName: string, methodName: string, inputArguments: Argument[]): Promise<[Uint8Array, string]> { 47 | const [req, rawTxId] = await encodeSendTransactionRequest( 48 | { 49 | protocolVersion: PROTOCOL_VERSION, 50 | virtualChainId: this.virtualChainId, 51 | timestamp: new Date(), 52 | nanoNonce: this.bumpNanoNonce(), 53 | networkType: this.networkType, 54 | contractName: contractName, 55 | methodName: methodName, 56 | inputArguments: inputArguments, 57 | }, 58 | this.signer, 59 | ); 60 | return [req, Encoding.encodeHex(rawTxId)]; 61 | } 62 | 63 | async createDeployTransaction(contractName: string, processorType: number, ...sources: Uint8Array[]): Promise<[Uint8Array, string]> { 64 | const inputArguments: Argument[] = [ 65 | argString(contractName), 66 | argUint32(processorType), 67 | ...sources.map(argBytes) 68 | ]; 69 | 70 | return this.createTransaction("_Deployments", "deployService", inputArguments); 71 | } 72 | 73 | async createQuery(contractName: string, methodName: string, inputArguments: Argument[]): Promise { 74 | return encodeRunQueryRequest({ 75 | protocolVersion: PROTOCOL_VERSION, 76 | virtualChainId: this.virtualChainId, 77 | timestamp: new Date(), 78 | networkType: this.networkType, 79 | contractName: contractName, 80 | methodName: methodName, 81 | inputArguments: inputArguments, 82 | }, this.signer); 83 | } 84 | 85 | protected createGetTransactionStatusPayload(txId: string): Uint8Array { 86 | const rawTxId = Encoding.decodeHex(txId); 87 | return encodeGetTransactionStatusRequest({ 88 | protocolVersion: PROTOCOL_VERSION, 89 | virtualChainId: this.virtualChainId, 90 | txId: rawTxId, 91 | }); 92 | } 93 | 94 | protected createGetTransactionReceiptProofPayload(txId: string): Uint8Array { 95 | const rawTxId = Encoding.decodeHex(txId); 96 | return encodeGetTransactionReceiptProofRequest({ 97 | protocolVersion: PROTOCOL_VERSION, 98 | virtualChainId: this.virtualChainId, 99 | txId: rawTxId, 100 | }); 101 | } 102 | 103 | protected createGetBlockPayload(blockHeight: bigint): Uint8Array { 104 | return encodeGetBlockRequest({ 105 | protocolVersion: PROTOCOL_VERSION, 106 | virtualChainId: this.virtualChainId, 107 | blockHeight: blockHeight, 108 | }); 109 | } 110 | 111 | async sendTransaction(rawTransaction: Uint8Array): Promise { 112 | const res = await this.sendHttpPost(SEND_TRANSACTION_URL, rawTransaction); 113 | return decodeSendTransactionResponse(res); 114 | } 115 | 116 | async sendQuery(rawQuery: Uint8Array): Promise { 117 | const res = await this.sendHttpPost(RUN_QUERY_URL, rawQuery); 118 | return decodeRunQueryResponse(res); 119 | } 120 | 121 | async getTransactionStatus(txId: string): Promise { 122 | const payload = this.createGetTransactionStatusPayload(txId); 123 | const res = await this.sendHttpPost(GET_TRANSACTION_STATUS_URL, payload); 124 | return decodeGetTransactionStatusResponse(res); 125 | } 126 | 127 | async getTransactionReceiptProof(txId: string): Promise { 128 | const payload = this.createGetTransactionReceiptProofPayload(txId); 129 | const res = await this.sendHttpPost(GET_TRANSACTION_RECEIPT_PROOF_URL, payload); 130 | return decodeGetTransactionReceiptProofResponse(res); 131 | } 132 | 133 | async getBlock(blockHeight: bigint): Promise { 134 | const payload = this.createGetBlockPayload(blockHeight); 135 | const res = await this.sendHttpPost(GET_BLOCK_URL, payload); 136 | return decodeGetBlockResponse(res); 137 | } 138 | 139 | private async sendHttpPost(relativeUrl: string, payload: Uint8Array): Promise { 140 | if (!payload || payload.byteLength == 0) { 141 | throw new Error(`payload sent by http is empty`); 142 | } 143 | 144 | const res = await axios.post(this.endpoint + relativeUrl, payload, { 145 | headers: { "content-type": CONTENT_TYPE_MEMBUFFERS }, 146 | responseType: "arraybuffer", 147 | validateStatus: status => true, 148 | }); 149 | 150 | // check if we have the content type response we expect 151 | const contentType = res.headers["content-type"]; 152 | if (contentType != CONTENT_TYPE_MEMBUFFERS) { 153 | if (contentType == "text/plain" || contentType == "application/json" || contentType == "text/html") { 154 | throw new Error(`http request failed: ${getTextDecoder().decode(res.data)}`); 155 | } else { 156 | throw new Error(`http request failed with unexpected Content-Type '${contentType}'`); 157 | } 158 | } 159 | 160 | if (!res.data) { 161 | throw new Error(`no response data available, http status: ${res.status} ${res.statusText}`); 162 | } 163 | 164 | if (res.data.constructor === ArrayBuffer) { 165 | return new Uint8Array(res.data); 166 | } 167 | 168 | return res.data; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /src/protocol/Base.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import { InternalBuilder } from "membuffers"; 10 | 11 | export abstract class BaseBuilder { 12 | protected builder: InternalBuilder; 13 | constructor() { 14 | this.builder = new InternalBuilder(); 15 | } 16 | abstract write(buf: Uint8Array): void; 17 | getSize() { 18 | return this.builder.getSize(); 19 | } 20 | calcRequiredSize() { 21 | this.write(null); 22 | return this.builder.getSize(); 23 | } 24 | build() { 25 | const buf = new Uint8Array(this.calcRequiredSize()); 26 | this.write(buf); 27 | return buf; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/protocol/Client.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import { BaseBuilder } from "./Base"; 10 | import * as Protocol from "./Protocol"; 11 | import { FieldTypes } from "membuffers"; 12 | 13 | export const RequestResult_Scheme = [FieldTypes.TypeUint16, FieldTypes.TypeUint64, FieldTypes.TypeUint64]; 14 | 15 | export class TransactionRefBuilder extends BaseBuilder { 16 | constructor( 17 | private fields: { 18 | protocolVersion: number; 19 | virtualChainId: number; 20 | transactionTimestamp: bigint; 21 | txHash: Uint8Array; 22 | }, 23 | ) { 24 | super(); 25 | } 26 | write(buf: Uint8Array): void { 27 | this.builder.reset(); 28 | this.builder.writeUint32(buf, this.fields.protocolVersion); 29 | this.builder.writeUint32(buf, this.fields.virtualChainId); 30 | this.builder.writeUint64(buf, this.fields.transactionTimestamp); 31 | this.builder.writeBytes(buf, this.fields.txHash); 32 | } 33 | } 34 | 35 | export const SendTransactionRequest_Scheme = [FieldTypes.TypeMessage]; 36 | 37 | export class SendTransactionRequestBuilder extends BaseBuilder { 38 | constructor( 39 | private fields: { 40 | signedTransaction: Protocol.SignedTransactionBuilder; 41 | }, 42 | ) { 43 | super(); 44 | } 45 | write(buf: Uint8Array): void { 46 | this.builder.reset(); 47 | this.builder.writeMessage(buf, this.fields.signedTransaction); 48 | } 49 | } 50 | 51 | export const SendTransactionResponse_Scheme = [FieldTypes.TypeMessage, FieldTypes.TypeUint16, FieldTypes.TypeMessage]; 52 | 53 | export class RunQueryRequestBuilder extends BaseBuilder { 54 | constructor( 55 | private fields: { 56 | signedQuery: Protocol.SignedQueryBuilder; 57 | }, 58 | ) { 59 | super(); 60 | } 61 | write(buf: Uint8Array): void { 62 | this.builder.reset(); 63 | this.builder.writeMessage(buf, this.fields.signedQuery); 64 | } 65 | } 66 | 67 | export const RunQueryResponse_Scheme = [FieldTypes.TypeMessage, FieldTypes.TypeMessage]; 68 | 69 | export class GetTransactionStatusRequestBuilder extends BaseBuilder { 70 | constructor( 71 | private fields: { 72 | transactionRef: TransactionRefBuilder; 73 | }, 74 | ) { 75 | super(); 76 | } 77 | write(buf: Uint8Array): void { 78 | this.builder.reset(); 79 | this.builder.writeMessage(buf, this.fields.transactionRef); 80 | } 81 | } 82 | 83 | export const GetTransactionStatusResponse_Scheme = [FieldTypes.TypeMessage, FieldTypes.TypeUint16, FieldTypes.TypeMessage]; 84 | 85 | export class GetTransactionReceiptProofRequestBuilder extends BaseBuilder { 86 | constructor( 87 | private fields: { 88 | transactionRef: TransactionRefBuilder; 89 | }, 90 | ) { 91 | super(); 92 | } 93 | write(buf: Uint8Array): void { 94 | this.builder.reset(); 95 | this.builder.writeMessage(buf, this.fields.transactionRef); 96 | } 97 | } 98 | 99 | export const GetTransactionReceiptProofResponse_Scheme = [FieldTypes.TypeMessage, FieldTypes.TypeUint16, FieldTypes.TypeMessage, FieldTypes.TypeBytes]; 100 | 101 | export class GetBlockRequestBuilder extends BaseBuilder { 102 | constructor( 103 | private fields: { 104 | protocolVersion: number; 105 | virtualChainId: number; 106 | blockHeight: bigint; 107 | }, 108 | ) { 109 | super(); 110 | } 111 | write(buf: Uint8Array): void { 112 | this.builder.reset(); 113 | this.builder.writeUint32(buf, this.fields.protocolVersion); 114 | this.builder.writeUint32(buf, this.fields.virtualChainId); 115 | this.builder.writeUint64(buf, this.fields.blockHeight); 116 | } 117 | } 118 | 119 | export const GetBlockResponse_Scheme = [ 120 | FieldTypes.TypeMessage, 121 | FieldTypes.TypeMessage, 122 | FieldTypes.TypeMessage, 123 | FieldTypes.TypeMessageArray, 124 | FieldTypes.TypeMessage, 125 | FieldTypes.TypeMessage, 126 | FieldTypes.TypeMessageArray, 127 | FieldTypes.TypeMessageArray, 128 | FieldTypes.TypeMessage, 129 | ]; 130 | -------------------------------------------------------------------------------- /src/protocol/Protocol.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | import { BaseBuilder } from "./Base"; 10 | import { FieldTypes } from "membuffers"; 11 | 12 | // nanoNonce = nanoseconds in range 0 - 499,999 (that will still round down to 0 in milliseconds) 13 | // used to give different timestamps to transactions created in the same millisecond 14 | export function dateToUnixNano(date: Date, nanoNonce: number): bigint { 15 | if (nanoNonce < 0 || nanoNonce > 499999) throw new Error(`nanoNonce is ${nanoNonce} and must be 0 - 499,999`); 16 | return (BigInt(date.getTime()) * BigInt(1000000)) + BigInt(nanoNonce); 17 | } 18 | 19 | export function unixNanoToDate(timestamp: bigint): Date { 20 | return new Date(Number(timestamp / BigInt(1000000))); 21 | } 22 | 23 | // The ordered values for the types is important for backwards compatibility (and cross platform compatibility) 24 | export const ARGUMENT_TYPE_UINT_32_VALUE = 0; 25 | export const ARGUMENT_TYPE_UINT_64_VALUE = 1; 26 | export const ARGUMENT_TYPE_STRING_VALUE = 2; 27 | export const ARGUMENT_TYPE_BYTES_VALUE = 3; 28 | export const ARGUMENT_TYPE_BOOL_VALUE = 4; 29 | export const ARGUMENT_TYPE_UINT_256_VALUE = 5; 30 | export const ARGUMENT_TYPE_BYTES_20_VALUE = 6; 31 | export const ARGUMENT_TYPE_BYTES_32_VALUE = 7; 32 | export const ARGUMENT_TYPE_UINT_32_ARRAY_VALUE = 8; 33 | export const ARGUMENT_TYPE_UINT_64_ARRAY_VALUE = 9; 34 | export const ARGUMENT_TYPE_STRING_ARRAY_VALUE = 10; 35 | export const ARGUMENT_TYPE_BYTES_ARRAY_VALUE = 11; 36 | export const ARGUMENT_TYPE_BOOL_ARRAY_VALUE = 12; 37 | export const ARGUMENT_TYPE_UINT_256_ARRAY_VALUE = 13; 38 | export const ARGUMENT_TYPE_BYTES_20_ARRAY_VALUE = 14; 39 | export const ARGUMENT_TYPE_BYTES_32_ARRAY_VALUE = 15; 40 | 41 | export const Argument_Scheme = [FieldTypes.TypeUnion]; 42 | export const Argument_Unions = [[ 43 | FieldTypes.TypeUint32, FieldTypes.TypeUint64, FieldTypes.TypeString, FieldTypes.TypeBytes, 44 | FieldTypes.TypeBool, FieldTypes.TypeUint256, FieldTypes.TypeBytes20, FieldTypes.TypeBytes32, 45 | FieldTypes.TypeUint32Array, FieldTypes.TypeUint64Array, FieldTypes.TypeStringArray, FieldTypes.TypeBytesArray, 46 | FieldTypes.TypeBoolArray, FieldTypes.TypeUint256Array, FieldTypes.TypeBytes20Array, FieldTypes.TypeBytes32Array, 47 | ]]; 48 | 49 | export class ArgumentBuilder extends BaseBuilder { 50 | constructor( 51 | private fields: { 52 | type: number; 53 | value: number | bigint | string | Uint8Array | boolean | Array | Array | Array | Array | Array; 54 | }, 55 | ) { 56 | super(); 57 | } 58 | write(buf: Uint8Array): void { 59 | this.builder.reset(); 60 | this.builder.writeUnionIndex(buf, this.fields.type); 61 | switch (this.fields.type) { 62 | case ARGUMENT_TYPE_UINT_32_VALUE: 63 | this.builder.writeUint32(buf, this.fields.value); 64 | break; 65 | case ARGUMENT_TYPE_UINT_64_VALUE: 66 | this.builder.writeUint64(buf, this.fields.value); 67 | break; 68 | case ARGUMENT_TYPE_STRING_VALUE: 69 | this.builder.writeString(buf, this.fields.value); 70 | break; 71 | case ARGUMENT_TYPE_BYTES_VALUE: 72 | this.builder.writeBytes(buf, this.fields.value); 73 | break; 74 | case ARGUMENT_TYPE_BOOL_VALUE: 75 | this.builder.writeBool(buf, this.fields.value); 76 | break; 77 | case ARGUMENT_TYPE_UINT_256_VALUE: 78 | this.builder.writeUint256(buf, this.fields.value); 79 | break; 80 | case ARGUMENT_TYPE_BYTES_20_VALUE: 81 | this.builder.writeBytes20(buf, this.fields.value); 82 | break; 83 | case ARGUMENT_TYPE_BYTES_32_VALUE: 84 | this.builder.writeBytes32(buf, this.fields.value); 85 | break; 86 | case ARGUMENT_TYPE_UINT_32_ARRAY_VALUE: 87 | this.builder.writeUint32Array(buf, >this.fields.value); 88 | break; 89 | case ARGUMENT_TYPE_UINT_64_ARRAY_VALUE: 90 | this.builder.writeUint64Array(buf, >this.fields.value); 91 | break; 92 | case ARGUMENT_TYPE_STRING_ARRAY_VALUE: 93 | this.builder.writeStringArray(buf, >this.fields.value); 94 | break; 95 | case ARGUMENT_TYPE_BYTES_ARRAY_VALUE: 96 | this.builder.writeBytesArray(buf, >this.fields.value); 97 | break; 98 | case ARGUMENT_TYPE_BOOL_ARRAY_VALUE: 99 | this.builder.writeBoolArray(buf, >this.fields.value); 100 | break; 101 | case ARGUMENT_TYPE_UINT_256_ARRAY_VALUE: 102 | this.builder.writeUint256Array(buf, >this.fields.value); 103 | break; 104 | case ARGUMENT_TYPE_BYTES_20_ARRAY_VALUE: 105 | this.builder.writeBytes20Array(buf, >this.fields.value); 106 | break; 107 | case ARGUMENT_TYPE_BYTES_32_ARRAY_VALUE: 108 | this.builder.writeBytes32Array(buf, >this.fields.value); 109 | break; 110 | default: 111 | throw new Error(`unknown Argument type ${this.fields.type}`); 112 | } 113 | } 114 | } 115 | 116 | export const ArgumentArray_Scheme = [FieldTypes.TypeMessageArray]; 117 | 118 | export class ArgumentArrayBuilder extends BaseBuilder { 119 | constructor( 120 | private fields: { 121 | arguments: ArgumentBuilder[]; 122 | }, 123 | ) { 124 | super(); 125 | } 126 | write(buf: Uint8Array): void { 127 | this.builder.reset(); 128 | this.builder.writeMessageArray(buf, this.fields.arguments); 129 | } 130 | } 131 | 132 | export const Event_Scheme = [FieldTypes.TypeString, FieldTypes.TypeString, FieldTypes.TypeBytes]; 133 | export const EventsArray_Scheme = [FieldTypes.TypeMessageArray]; 134 | 135 | export class EdDSA01SignerBuilder extends BaseBuilder { 136 | constructor( 137 | private fields: { 138 | networkType: number; 139 | signerPublicKey: Uint8Array; 140 | }, 141 | ) { 142 | super(); 143 | } 144 | write(buf: Uint8Array): void { 145 | this.builder.reset(); 146 | this.builder.writeUint16(buf, this.fields.networkType); 147 | this.builder.writeBytes(buf, this.fields.signerPublicKey); 148 | } 149 | } 150 | 151 | export class SignerBuilder extends BaseBuilder { 152 | constructor( 153 | private fields: { 154 | scheme: number; 155 | eddsa: EdDSA01SignerBuilder; 156 | }, 157 | ) { 158 | super(); 159 | } 160 | write(buf: Uint8Array): void { 161 | this.builder.reset(); 162 | this.builder.writeUnionIndex(buf, this.fields.scheme); 163 | switch (this.fields.scheme) { 164 | case 0: 165 | this.builder.writeMessage(buf, this.fields.eddsa); 166 | break; 167 | default: 168 | throw new Error(`unknown Signer scheme ${this.fields.scheme}`); 169 | } 170 | } 171 | } 172 | 173 | export const Signer_Scheme = [FieldTypes.TypeUnion]; 174 | export const Signer_Unions = [[FieldTypes.TypeMessage, FieldTypes.TypeMessage]]; 175 | 176 | export const EdDSA01Signer_Scheme = [FieldTypes.TypeUint16, FieldTypes.TypeBytes]; 177 | 178 | export class TransactionBuilder extends BaseBuilder { 179 | constructor( 180 | private fields: { 181 | protocolVersion: number; 182 | virtualChainId: number; 183 | timestamp: bigint; 184 | signer: SignerBuilder; 185 | contractName: string; 186 | methodName: string; 187 | inputArgumentArray: Uint8Array; 188 | }, 189 | ) { 190 | super(); 191 | } 192 | write(buf: Uint8Array): void { 193 | this.builder.reset(); 194 | this.builder.writeUint32(buf, this.fields.protocolVersion); 195 | this.builder.writeUint32(buf, this.fields.virtualChainId); 196 | this.builder.writeUint64(buf, this.fields.timestamp); 197 | this.builder.writeMessage(buf, this.fields.signer); 198 | this.builder.writeString(buf, this.fields.contractName); 199 | this.builder.writeString(buf, this.fields.methodName); 200 | this.builder.writeBytes(buf, this.fields.inputArgumentArray); 201 | } 202 | } 203 | 204 | export const Transaction_Scheme = [FieldTypes.TypeUint32, FieldTypes.TypeUint32, FieldTypes.TypeUint64, FieldTypes.TypeMessage, FieldTypes.TypeString, FieldTypes.TypeString, FieldTypes.TypeBytes]; 205 | 206 | export const SignedTransaction_Scheme = [FieldTypes.TypeMessage, FieldTypes.TypeBytes]; 207 | 208 | export class SignedTransactionBuilder extends BaseBuilder { 209 | constructor( 210 | private fields: { 211 | transaction: TransactionBuilder; 212 | signature: Uint8Array; 213 | }, 214 | ) { 215 | super(); 216 | } 217 | write(buf: Uint8Array): void { 218 | this.builder.reset(); 219 | this.builder.writeMessage(buf, this.fields.transaction); 220 | this.builder.writeBytes(buf, this.fields.signature); 221 | } 222 | } 223 | 224 | export const TransactionReceipt_Scheme = [FieldTypes.TypeBytes, FieldTypes.TypeUint16, FieldTypes.TypeBytes, FieldTypes.TypeBytes]; 225 | 226 | export class QueryBuilder extends BaseBuilder { 227 | constructor( 228 | private fields: { 229 | protocolVersion: number; 230 | virtualChainId: number; 231 | timestamp: bigint; 232 | signer: SignerBuilder; 233 | contractName: string; 234 | methodName: string; 235 | inputArgumentArray: Uint8Array; 236 | }, 237 | ) { 238 | super(); 239 | } 240 | write(buf: Uint8Array): void { 241 | this.builder.reset(); 242 | this.builder.writeUint32(buf, this.fields.protocolVersion); 243 | this.builder.writeUint32(buf, this.fields.virtualChainId); 244 | this.builder.writeUint64(buf, this.fields.timestamp); 245 | this.builder.writeMessage(buf, this.fields.signer); 246 | this.builder.writeString(buf, this.fields.contractName); 247 | this.builder.writeString(buf, this.fields.methodName); 248 | this.builder.writeBytes(buf, this.fields.inputArgumentArray); 249 | } 250 | } 251 | 252 | export const SignedQuery_Scheme = [FieldTypes.TypeMessage, FieldTypes.TypeBytes]; 253 | 254 | export class SignedQueryBuilder extends BaseBuilder { 255 | constructor( 256 | private fields: { 257 | query: QueryBuilder; 258 | signature: Uint8Array; 259 | }, 260 | ) { 261 | super(); 262 | } 263 | write(buf: Uint8Array): void { 264 | this.builder.reset(); 265 | this.builder.writeMessage(buf, this.fields.query); 266 | this.builder.writeBytes(buf, this.fields.signature); 267 | } 268 | } 269 | 270 | export const QueryResult_Scheme = [FieldTypes.TypeUint16, FieldTypes.TypeBytes, FieldTypes.TypeBytes]; 271 | 272 | export const TransactionsBlockHeader_Scheme = [ 273 | FieldTypes.TypeUint32, 274 | FieldTypes.TypeUint32, 275 | FieldTypes.TypeUint64, 276 | FieldTypes.TypeBytes, 277 | FieldTypes.TypeUint64, 278 | FieldTypes.TypeBytes, 279 | FieldTypes.TypeBytes, 280 | FieldTypes.TypeUint32, 281 | FieldTypes.TypeBytes, 282 | FieldTypes.TypeUint32 283 | ]; 284 | 285 | export const ResultsBlockHeader_Scheme = [ 286 | FieldTypes.TypeUint32, 287 | FieldTypes.TypeUint32, 288 | FieldTypes.TypeUint64, 289 | FieldTypes.TypeBytes, 290 | FieldTypes.TypeUint64, 291 | FieldTypes.TypeBytes, 292 | FieldTypes.TypeBytes, 293 | FieldTypes.TypeBytes, 294 | FieldTypes.TypeBytes, 295 | FieldTypes.TypeUint32, 296 | FieldTypes.TypeUint32, 297 | FieldTypes.TypeBytes, 298 | FieldTypes.TypeUint32 299 | ]; 300 | -------------------------------------------------------------------------------- /src/types/bigint.d.ts: -------------------------------------------------------------------------------- 1 | /* 2 | interface BigInt extends Object {} 3 | interface BigIntConstructor { 4 | new(value: any): BigInt; 5 | (value: any): BigInt; 6 | asUintN(bits: number, bigint: BigInt): BigInt; 7 | asIntN(bits: number, bigint: BigInt): BigInt; 8 | } 9 | declare var BigInt: BigIntConstructor; 10 | */ 11 | 12 | interface DataView { 13 | getBigInt64(byteOffset: number, littleEndian?: boolean): bigint; 14 | getBigUint64(byteOffset: number, littleEndian?: boolean): bigint; 15 | setBigInt64(byteOffset: number, value: bigint, littleEndian?: boolean): void; 16 | setBigUint64(byteOffset: number, value: bigint, littleEndian?: boolean): void; 17 | } 18 | -------------------------------------------------------------------------------- /src/types/externals.d.ts: -------------------------------------------------------------------------------- 1 | declare module "elliptic"; 2 | -------------------------------------------------------------------------------- /src/types/get-random-values.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'get-random-values'; -------------------------------------------------------------------------------- /src/types/text-encoding.d.ts: -------------------------------------------------------------------------------- 1 | declare class TextDecoder { 2 | readonly encoding: string; 3 | readonly fatal: boolean; 4 | readonly ignoreBOM: boolean; 5 | constructor(encoding?: string, options?: { fatal?: boolean; ignoreBOM?: boolean }); 6 | decode(input?: any, options?: { stream?: boolean }): string; 7 | } 8 | 9 | declare class TextEncoder { 10 | readonly encoding: string; 11 | constructor(); 12 | encode(input?: string): Uint8Array; 13 | } 14 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | npm run build 2 | npm run test -------------------------------------------------------------------------------- /tsconfig-for-types.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationDir": "./dist", 5 | "module": "es6", 6 | "noImplicitAny": true, 7 | "outDir": "./dist", 8 | "target": "esnext", 9 | "esModuleInterop": true, 10 | "moduleResolution": "node", 11 | "downlevelIteration": true, 12 | "emitDeclarationOnly": true, 13 | "lib": ["esnext"], 14 | "types": [] 15 | }, 16 | "include": ["src/lib.ts", "src/types/**/*.ts"] 17 | } 18 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "declarationDir": "./dist", 5 | "module": "es6", 6 | "noImplicitAny": true, 7 | "outDir": "./dist", 8 | "target": "esnext", 9 | "esModuleInterop": true, 10 | "moduleResolution": "node", 11 | "downlevelIteration": true, 12 | "lib": ["esnext", "esnext.bigint"], 13 | "types": ["node", "jest"] 14 | }, 15 | "include": ["src/index.ts", "src/types/**/*.ts", "src/**/*.test.ts"] 16 | } 17 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [true, "check-space"], 5 | "indent": [true, "spaces"], 6 | "one-line": [true, "check-open-brace", "check-whitespace"], 7 | "no-var-keyword": true, 8 | "quotemark": [true, "double", "avoid-escape"], 9 | "semicolon": [true, "always", "ignore-bound-class-methods"], 10 | "whitespace": [true, "check-branch", "check-decl", "check-operator", "check-module", "check-separator", "check-type"], 11 | "typedef-whitespace": [ 12 | true, 13 | { 14 | "call-signature": "nospace", 15 | "index-signature": "nospace", 16 | "parameter": "nospace", 17 | "property-declaration": "nospace", 18 | "variable-declaration": "nospace" 19 | }, 20 | { 21 | "call-signature": "onespace", 22 | "index-signature": "onespace", 23 | "parameter": "onespace", 24 | "property-declaration": "onespace", 25 | "variable-declaration": "onespace" 26 | } 27 | ], 28 | "no-internal-module": true, 29 | "no-trailing-whitespace": true, 30 | "prefer-const": true, 31 | "jsdoc-format": true 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 the orbs-client-sdk-javascript authors 3 | * This file is part of the orbs-client-sdk-javascript library in the Orbs project. 4 | * 5 | * This source code is licensed under the MIT license found in the LICENSE file in the root directory of this source tree. 6 | * The above notice should be included in all copies or substantial portions of the software. 7 | */ 8 | 9 | const path = require("path"); 10 | 11 | const production = process.env.NODE_ENV === "production"; 12 | const libraryName = 'Orbs'; 13 | 14 | const webConfig = { 15 | target: 'web', 16 | mode: production ? "production" : "development", 17 | devtool: production ? "" : "inline-source-map", 18 | entry: "./src/index.ts", 19 | output: { 20 | path: path.join(__dirname, "dist"), 21 | filename: `orbs-client-sdk-web.js`, 22 | library: libraryName, 23 | libraryTarget: "umd", 24 | umdNamedDefine: true 25 | }, 26 | resolve: { 27 | extensions: [".js", ".ts"], 28 | }, 29 | module: { 30 | rules: [ 31 | { 32 | test: /\.ts$/, 33 | loaders: ["babel-loader"], 34 | }, 35 | ], 36 | }, 37 | }; 38 | 39 | const nodeConfig = { 40 | target: 'node', 41 | mode: production ? "production" : "development", 42 | devtool: production ? "" : "inline-source-map", 43 | entry: "./src/index.ts", 44 | output: { 45 | path: path.join(__dirname, "dist"), 46 | filename: `orbs-client-sdk.js`, 47 | library: libraryName, 48 | libraryTarget: "umd", 49 | umdNamedDefine: true 50 | }, 51 | resolve: { 52 | extensions: [".js", ".ts"], 53 | }, 54 | module: { 55 | rules: [ 56 | { 57 | test: /\.ts$/, 58 | loaders: ["babel-loader"], 59 | }, 60 | ], 61 | }, 62 | }; 63 | 64 | module.exports = [webConfig, nodeConfig]; --------------------------------------------------------------------------------