├── .gitignore ├── LICENSE ├── README.md ├── __tests__ ├── client.test.js ├── crypto.test.js ├── feesplit.test.js ├── ibc.test.js ├── secp256k1wallet.test.js ├── wasm.test.js └── wasm_contract │ ├── burner.wasm │ └── hackatom.wasm ├── docs ├── okexchain-jssdk-doc-client.md └── okexchain-jssdk-doc-crypto.md ├── jest.config.js ├── package-lock.json ├── package.json ├── src ├── client.js ├── crypto │ ├── fix-opts.js │ ├── index.js │ ├── scrypt-rom.js │ └── scrypt-sync.js ├── httpProxy.js ├── index.js ├── rpcProxy.js ├── secp256k1 │ └── secp256k1wallet.js ├── transaction.js ├── utils │ ├── encoderHelper.js │ ├── index.js │ ├── request.js │ └── validateHelper.js └── wallet │ ├── connector.js │ └── index.js └── version-mapping.md /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | *.log 3 | .idea/ 4 | ###Mac OS### 5 | .DS_Store 6 | /buildTest 7 | .vscode/ 8 | tsconfig.json 9 | .history/ 10 | /dist 11 | /bulid 12 | /lib 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2018-2019 OK 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OKEXChain JavaScript SDK 2 | 3 | The OKEXChain JavaScript SDK allows browsers and node.js clients to interact with OKEXChain. It includes the following core components: 4 | 5 | * **crypto** - core cryptographic functions. 6 | * **client** - implementations of OKEXChain transaction types, such as for transfers and trading. 7 | * **accounts** - management of "accounts" and wallets, including seed and encrypted mnemonic generation. 8 | 9 | # Installation 10 | 11 | Install the NPM package: 12 | ```bash 13 | $ npm i @okexchain/javascript-sdk 14 | ``` 15 | 16 | # API 17 | 18 | For up-to-date API documentation, please check the [wiki](https://github.com/okex/okexchain-javascript-sdk/blob/master/docs/okexchain-jssdk-doc.md). 19 | 20 | # Testing 21 | 22 | All new code changes should be covered with unit tests. You can run the tests with the following command: 23 | 24 | ```bash 25 | $ npm run test 26 | ``` 27 | 28 | # Contributing 29 | 30 | Contributions to the OKEXChain JavaScript SDK are welcome. Please ensure that you have tested the changes with a local client and have added unit test coverage for your code. 31 | -------------------------------------------------------------------------------- /__tests__/client.test.js: -------------------------------------------------------------------------------- 1 | import OKEXChainClient from "../src" 2 | import * as crypto from "../src/crypto" 3 | 4 | 5 | 6 | // const mnemonic = "total lottery arena when pudding best candy until army spoil drill pool" 7 | // const privateKey_996 = "29892b64003fc5c8c89dc795a2ae82aa84353bb4352f28707c2ed32aa1011884" 8 | // const privateKey = "828e61f969a7369f3340b07dd2080740d8445d7f802899ddacf9bc4db8608997" 9 | // const from_996 = "ex1jjvpmgwwgs99nhlje3aag0lackunqgj7pcgnd4" 10 | // const from = "ex1ya7dn2rr8nx07tx9ksq8gvz5utvarrh0knjnjn" 11 | 12 | const serverUrl = "https://exchaintestrpc.okex.org" 13 | const toAddress = "ex1ya7dn2rr8nx07tx9ksq8gvz5utvarrh0knjnjn" 14 | const chainId = "exchain-65" 15 | const baseCoin = "okt" 16 | const testCoin = "xxb-781" 17 | const testProduct = testCoin + "_" + baseCoin 18 | const testPoolName = "aaa-882_okt" 19 | 20 | 21 | const mnemonic = "bamboo dismiss pitch mass strategy advice example critic vapor series simple kitten" 22 | const privateKey = "828e61f969a7369f3340b07dd2080740d8445d7f802899ddacf9bc4db8608997" 23 | const from = "ex1vegcudd5ypa6j025w4tf6hspt0vr27ty5sy3l9" 24 | 25 | 26 | describe("OKEXChainClient test", async () => { 27 | 28 | 29 | it("get balance", async () => { 30 | const client = new OKEXChainClient(serverUrl, { 31 | chainId: chainId, 32 | relativePath: "/okexchain-test/v1", 33 | isMainnet: false 34 | }) 35 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '60') 36 | await client.setAccountInfo(privateKey) 37 | const res = await client.getBalance(from) 38 | console.log(res) 39 | expect(res.length).toBeGreaterThanOrEqual(0) 40 | }) 41 | 42 | 43 | 44 | it("send sendTransaction", async () => { 45 | jest.setTimeout(10000) 46 | const client = new OKEXChainClient(serverUrl, { 47 | chainId: chainId, 48 | relativePath: "/exchain/v1", 49 | isMainnet: false 50 | }) 51 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '118') 52 | await client.setAccountInfo(privateKey) 53 | //console.log(client) 54 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 55 | console.log(addr) 56 | const account = await client.getAccount(addr) 57 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 58 | // console.log(account, sequence) 59 | const res = await client.sendSendTransaction(toAddress, "1.00000000", baseCoin, "hello world", sequence) 60 | console.log(JSON.stringify(res)) 61 | // expect(res.status).toBe(200) 62 | }) 63 | 64 | 65 | 66 | it("send sendTransaction on dev", async () => { 67 | jest.setTimeout(10000) 68 | const client = new OKEXChainClient("http://127.0.0.1:36659", { 69 | chainId: "exchain-101", 70 | relativePath: "/exchain/v1", 71 | isMainnet: false 72 | }) 73 | const privateKey = crypto.getPrivateKeyFromMnemonic("giggle sibling fun arrow elevator spoon blood grocery laugh tortoise culture tool", '60') 74 | await client.setAccountInfo(privateKey) 75 | //console.log(client) 76 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 77 | const account = await client.getAccount(addr) 78 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 79 | // console.log(account, sequence) 80 | const res = await client.sendSendTransaction(toAddress, "100", "okt", "hello world", sequence) 81 | console.log(JSON.stringify(res)) 82 | // expect(res.status).toBe(200) 83 | }) 84 | 85 | it("send placeOrderTransaction,cancelOrderTransaction", async () => { 86 | jest.setTimeout(20000) 87 | const symbol = testProduct 88 | const client = new OKEXChainClient(serverUrl, { 89 | chainId: chainId 90 | }) 91 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic) 92 | await client.setAccountInfo(privateKey) 93 | //console.log(client) 94 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 95 | //console.log(addr) 96 | const account = await client.getAccount(addr) 97 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 98 | 99 | const res1 = await client.sendPlaceOrderTransaction(symbol, "BUY", "1.00000000", "1.10000000", "",sequence) 100 | console.log(JSON.stringify(res1)) 101 | expect(res1.status).toBe(200) 102 | 103 | var patt = /ID[0-9]*-[0-9]*/ 104 | const orderId = patt.exec(JSON.stringify(res1))[0].toString() 105 | //const orderId = res1.result.tags[1].value 106 | console.log(orderId) 107 | const res2 = await client.sendCancelOrderTransaction(orderId, "",sequence + 1) 108 | console.log(JSON.stringify(res2)) 109 | expect(res2.status).toBe(200) 110 | 111 | }) 112 | 113 | async function prepareAccount() { 114 | const client = new OKEXChainClient(serverUrl, { 115 | chainId: chainId 116 | }) 117 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic) 118 | await client.setAccountInfo(privateKey) 119 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 120 | const account = await client.getAccount(addr) 121 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 122 | return { 123 | okclient:client, 124 | sequence:sequence 125 | } 126 | } 127 | 128 | it("send sendTokenIssueTransaction", async () => { 129 | jest.setTimeout(10000) 130 | const data = await prepareAccount() 131 | const res = await data.okclient.sendTokenIssueTransaction("aa", "aa11", "10000.00000000", true, '', 'test') 132 | console.log(JSON.stringify(res)) 133 | expect(res.status).toBe(200) 134 | }) 135 | it("send sendTokenBurnTransaction", async () => { 136 | jest.setTimeout(10000) 137 | const data = await prepareAccount() 138 | const res = await data.okclient.sendTokenBurnTransaction("aa", "100.00000000", "burn") 139 | console.log(JSON.stringify(res)) 140 | expect(res.status).toBe(200) 141 | }) 142 | it("send sendTokenMintTransaction", async () => { 143 | jest.setTimeout(10000) 144 | const data = await prepareAccount() 145 | const res = await data.okclient.sendTokenMintTransaction("aa", "200.00000000", "mint") 146 | console.log(JSON.stringify(res)) 147 | expect(res.status).toBe(200) 148 | }) 149 | 150 | 151 | it("send sendRegisterDexOperatorTransaction", async () => { 152 | jest.setTimeout(10000) 153 | const data = await prepareAccount() 154 | const res = await data.okclient.sendRegisterDexOperatorTransaction("http://test.json", "ex1ya7dn2rr8nx07tx9ksq8gvz5utvarrh0knjnjn", "add deposit", data.sequence) 155 | console.log(JSON.stringify(res)) 156 | expect(res.status).toBe(200) 157 | }) 158 | 159 | it("send sendListTokenPairTransaction", async () => { 160 | jest.setTimeout(10000) 161 | const data = await prepareAccount() 162 | const res = await data.okclient.sendListTokenPairTransaction("tbtc-edc", "tusdk-d42","0.01000000", "list tokenpair", data.sequence) 163 | console.log(JSON.stringify(res)) 164 | expect(res.status).toBe(200) 165 | }) 166 | 167 | it("send sendAddProductDepositTransaction", async () => { 168 | jest.setTimeout(10000) 169 | const data = await prepareAccount() 170 | const res = await data.okclient.sendAddProductDepositTransaction("50.00000000", "tbtc-edc_tusdk-d42", "add deposit", data.sequence) 171 | console.log(JSON.stringify(res)) 172 | expect(res.status).toBe(200) 173 | }) 174 | 175 | it("send sendWithdrawProductDepositTransaction", async () => { 176 | jest.setTimeout(10000) 177 | const data = await prepareAccount() 178 | const res = await data.okclient.sendWithdrawProductDepositTransaction("40.00000000", "tbtc-edc_tusdk-d42", "withdraw deposit", data.sequence) 179 | console.log(JSON.stringify(res)) 180 | expect(res.status).toBe(200) 181 | }) 182 | 183 | // ammswap 184 | it("send AddLiquidityTransaction", async () => { 185 | jest.setTimeout(10000) 186 | const data = await prepareAccount() 187 | const res = await data.okclient.sendAddLiquidityTransaction("0.01001000", "100.00000000", "eth", "200.00000000", 'okt', "1619677667", 'AddLiquidityTransaction', data.sequence) 188 | console.log(JSON.stringify(res)) 189 | expect(res.status).toBe(200) 190 | }) 191 | it("send RemoveLiquidityTransaction", async () => { 192 | jest.setTimeout(10000) 193 | const data = await prepareAccount() 194 | const res = await data.okclient.sendRemoveLiquidityTransaction("0.01001000", "50.00000000", "eth", "100.00000000", 'okt', "1619677667", 'RemoveLiquidityTransaction', data.sequence) 195 | console.log(JSON.stringify(res)) 196 | expect(res.status).toBe(200) 197 | }) 198 | it("send CreateExchangeTransaction", async () => { 199 | jest.setTimeout(10000) 200 | const data = await prepareAccount() 201 | const res = await data.okclient.sendCreateExchangeTransaction("eth", "okt", "CreateExchangeTransaction", data.sequence) 202 | console.log(JSON.stringify(res)) 203 | expect(res.status).toBe(200) 204 | }) 205 | it("send SwapTokenTransaction", async () => { 206 | jest.setTimeout(10000) 207 | const data = await prepareAccount() 208 | const res = await data.okclient.sendSwapTokenTransaction("50.00000000", "aa11", "10.00000000", "okt", "1612781334", toAddress, '', data.sequence) 209 | console.log(JSON.stringify(res)) 210 | expect(res.status).toBe(200) 211 | }) 212 | 213 | // farm 214 | it("send sendFarmCreatePoolTransaction", async () => { 215 | jest.setTimeout(10000) 216 | const client = new OKEXChainClient(serverUrl, { 217 | chainId: chainId 218 | }) 219 | // const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic) 220 | await client.setAccountInfo(privateKey) 221 | //console.log(client) 222 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 223 | const account = await client.getAccount(addr) 224 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 225 | const res = await client.sendFarmCreatePoolTransaction(testPoolName, baseCoin, 15, testCoin, "hello world", sequence) 226 | console.log(JSON.stringify(res)) 227 | // expect(res.status).toBe(200) 228 | }) 229 | 230 | it("send sendFarmDestroyPoolTransaction", async () => { 231 | jest.setTimeout(10000) 232 | const client = new OKEXChainClient(serverUrl, { 233 | chainId: chainId 234 | }) 235 | // const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic) 236 | await client.setAccountInfo(privateKey) 237 | //console.log(client) 238 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 239 | const account = await client.getAccount(addr) 240 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 241 | const res = await client.sendFarmDestroyPoolTransaction(testPoolName, "hello world", sequence) 242 | console.log(JSON.stringify(res)) 243 | // expect(res.status).toBe(200) 244 | }) 245 | 246 | it("send sendFarmProvideTransaction", async () => { 247 | jest.setTimeout(10000) 248 | const client = new OKEXChainClient(serverUrl, { 249 | chainId: chainId 250 | }) 251 | // const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic) 252 | await client.setAccountInfo(privateKey) 253 | //console.log(client) 254 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 255 | const account = await client.getAccount(addr) 256 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 257 | const res = await client.sendFarmProvideTransaction(testPoolName, testCoin, 100, 2, "11450", "hello world", sequence) 258 | console.log(JSON.stringify(res)) 259 | // expect(res.status).toBe(200) 260 | }) 261 | 262 | it("send sendFarmLockTransaction", async () => { 263 | jest.setTimeout(10000) 264 | const client = new OKEXChainClient(serverUrl, { 265 | chainId: chainId 266 | }) 267 | // const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic) 268 | await client.setAccountInfo(privateKey) 269 | //console.log(client) 270 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 271 | const account = await client.getAccount(addr) 272 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 273 | const res = await client.sendFarmLockTransaction(testPoolName, baseCoin, 1000, "hello world", sequence) 274 | console.log(JSON.stringify(res)) 275 | // expect(res.status).toBe(200) 276 | }) 277 | 278 | it("send sendFarmUnLockTransaction", async () => { 279 | jest.setTimeout(10000) 280 | const client = new OKEXChainClient(serverUrl, { 281 | chainId: chainId 282 | }) 283 | // const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic) 284 | await client.setAccountInfo(privateKey) 285 | //console.log(client) 286 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 287 | const account = await client.getAccount(addr) 288 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 289 | const res = await client.sendFarmUnLockTransaction(testPoolName, baseCoin, 500, "hello world", sequence) 290 | console.log(JSON.stringify(res)) 291 | // expect(res.status).toBe(200) 292 | }) 293 | 294 | it("send sendFarmClaimTransaction", async () => { 295 | jest.setTimeout(10000) 296 | const client = new OKEXChainClient(serverUrl, { 297 | chainId: chainId 298 | }) 299 | // const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic) 300 | await client.setAccountInfo(privateKey) 301 | //console.log(client) 302 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 303 | const account = await client.getAccount(addr) 304 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 305 | const res = await client.sendFarmClaimTransaction(testPoolName , "hello world", sequence) 306 | console.log(JSON.stringify(res)) 307 | // expect(res.status).toBe(200) 308 | }) 309 | 310 | }) 311 | -------------------------------------------------------------------------------- /__tests__/crypto.test.js: -------------------------------------------------------------------------------- 1 | import { crypto } from "../src" 2 | import bip39 from "bip39" 3 | 4 | const privateKey = "29892b64003fc5c8c89dc795a2ae82aa84353bb4352f28707c2ed32aa1011884" 5 | 6 | 7 | describe("crypto", () => { 8 | 9 | it("getAddressFromPrivateKey", () => { 10 | const address = crypto.getAddressFromPrivateKey(privateKey) 11 | expect(address).toBe("ex1jjvpmgwwgs99nhlje3aag0lackunqgj7pcgnd4") 12 | expect(address.length).toBe(41) 13 | }) 14 | 15 | it("getAddressFromPrivateKeyLegacy", () => { 16 | const address = crypto.getAddressFromPrivateKeyLegacy(privateKey) 17 | expect(address).toBe("ex1g7c3nvac7mjgn2m9mqllgat8wwd3aptd2947tz") 18 | expect(address.length).toBe(41) 19 | }) 20 | 21 | it("getAddressFromPubKey", () => { 22 | const publicKey = crypto.getPubKeyHexFromPrivateKey(privateKey) 23 | const address = crypto.getAddressFromPubKey(publicKey) 24 | expect(address).toBe("ex1jjvpmgwwgs99nhlje3aag0lackunqgj7pcgnd4") 25 | }) 26 | 27 | it("getPrivateKeyFromKeyStore", () => { 28 | const keyStore = crypto.generateKeyStore(privateKey, "ex") 29 | const pk = crypto.getPrivateKeyFromKeyStore(keyStore, "ex") 30 | expect(pk).toBe(privateKey) 31 | }) 32 | 33 | 34 | it("getPrivateKeyFromMnemonic", () => { 35 | const pk_60 = crypto.getPrivateKeyFromMnemonic("total lottery arena when pudding best candy until army spoil drill pool", '60') 36 | const pk_996 = crypto.getPrivateKeyFromMnemonic("total lottery arena when pudding best candy until army spoil drill pool", '996') 37 | const address_60 = crypto.getAddressFromPrivateKey(pk_60) 38 | const address_996 = crypto.getAddressFromPrivateKey(pk_996) 39 | console.log('address', address_60, address_996) 40 | expect(pk_60.toString("hex")).toBe("828e61f969a7369f3340b07dd2080740d8445d7f802899ddacf9bc4db8608997") 41 | expect(pk_996.toString("hex")).toBe("29892b64003fc5c8c89dc795a2ae82aa84353bb4352f28707c2ed32aa1011884") 42 | }) 43 | 44 | it("generateMnemonic", ()=>{ 45 | const mnemonic = crypto.generateMnemonic() 46 | expect(bip39.validateMnemonic(mnemonic)).toBe(true) 47 | }) 48 | 49 | it("decodeAddressToBuffer", ()=>{ 50 | let address = "ex1ya7dn2rr8nx07tx9ksq8gvz5utvarrh0knjnjn" 51 | const decod = crypto.decodeAddressToBuffer(address) 52 | console.log(decod.toString("hex")); 53 | expect(decod.toString("hex")).toBe("277cd9a8633cccff2cc5b400743054e2d9d18eef") 54 | }) 55 | 56 | it("sign", () => { 57 | const msg = "2f8b1705" 58 | const sig = crypto.sign(msg, privateKey).toString("hex") 59 | expect(sig).toBe("19d94b95f23ec8def89ac562bc47255fa138bec3185ca4e6ac6ee6912fd89cce095489ad872d1d54e303d6db33428095041f794d1c0c83a748b58befe6b98b8e") 60 | }) 61 | 62 | it("validateSig", () => { 63 | const publicKey = crypto.getPubKeyHexFromPrivateKey(privateKey) 64 | const msg = "2f8b1705" 65 | const sig = crypto.sign(msg, privateKey).toString("hex") 66 | expect(crypto.validateSig(sig, msg, publicKey)).toBeTruthy() 67 | }) 68 | 69 | it("convertBech32ToHex", () => { 70 | let bech32Address = "ex1ya7dn2rr8nx07tx9ksq8gvz5utvarrh0knjnjn" 71 | let newHexAddress = crypto.convertBech32ToHex(bech32Address) 72 | console.log('newHexAddress', newHexAddress); 73 | 74 | let hexAddress = "0x277CD9a8633ccCFF2Cc5B400743054e2d9d18eEf" 75 | let okexchainAddress = "okexchain1ya7dn2rr8nx07tx9ksq8gvz5utvarrh03cen3l" 76 | expect(hexAddress).toBe(newHexAddress[0]) 77 | expect(okexchainAddress).toBe(newHexAddress[1]) 78 | }) 79 | 80 | it("convertHexToBech32", () => { 81 | let hexAddress = "0x277CD9a8633ccCFF2Cc5B400743054e2d9d18eEf" 82 | let newBech32Address = crypto.convertHexToBech32(hexAddress) 83 | console.log('newBech32Address', newBech32Address) 84 | 85 | let exAddress = "ex1ya7dn2rr8nx07tx9ksq8gvz5utvarrh0knjnjn" 86 | let okexchainAddress = "okexchain1ya7dn2rr8nx07tx9ksq8gvz5utvarrh03cen3l" 87 | expect(exAddress).toBe(newBech32Address[0]) 88 | expect(okexchainAddress).toBe(newBech32Address[1]) 89 | }) 90 | 91 | it("convertOKExChainAddressToExAddress", () => { 92 | // let bech32Address = "okexchain1ya7dn2rr8nx07tx9ksq8gvz5utvarrh03cen3l" 93 | let bech32Address = "okexchain1jj8fggmk296f3adt8c469v8r2w3fkv03whjup2" 94 | let newBech32Address = crypto.convertOKExChainAddressToExAddress(bech32Address) 95 | console.log('newHexAddress', newBech32Address); 96 | }) 97 | 98 | 99 | }) 100 | -------------------------------------------------------------------------------- /__tests__/feesplit.test.js: -------------------------------------------------------------------------------- 1 | import OKEXChainClient from "../src" 2 | import * as crypto from "../src/crypto" 3 | const serverUrl = "https://exchaintestrpc.okex.org" 4 | 5 | const privateKey = '' 6 | // const privateKey = '' 7 | const contractAddress = '0x35a5A90BA0281189241f7abc3253664Ed0687B8E' 8 | const withdrawAddress = 'ex1fsfwwvl93qv6r56jpu084hxxzn9zphnyxhske5' 9 | const deployerAddress = 'ex1h0j8x0v9hs4eq6ppgamemfyu4vuvp2sl0q9p3v' 10 | const nonces = ['394684'] 11 | 12 | describe("okc wasm test", async function() { 13 | 14 | it("register feesplit ", async ()=> { 15 | jest.setTimeout(300000) 16 | const client = new OKEXChainClient(serverUrl, { 17 | chainId: "exchain-65", 18 | relativePath: "/okexchain-test/v1", 19 | isMainnet: false, 20 | }) 21 | 22 | await client.setAccountInfo(privateKey) 23 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 24 | console.log(addr) 25 | const account = await client.getAccount(addr) 26 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 27 | const fee = { 28 | amount: [{ 29 | amount: "0.030000000000000000", 30 | denom: "okt", 31 | 32 | }], 33 | gas: "100000000", 34 | } 35 | 36 | 37 | 38 | const res = await client.registerFeeSplit(contractAddress,'',nonces, fee,sequence) 39 | console.log(JSON.stringify(res)) 40 | }) 41 | 42 | it("update feesplit ", async ()=> { 43 | jest.setTimeout(300000) 44 | const client = new OKEXChainClient(serverUrl, { 45 | chainId: "exchain-65", 46 | relativePath: "/okexchain-test/v1", 47 | isMainnet: false, 48 | }) 49 | 50 | await client.setAccountInfo(privateKey) 51 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 52 | console.log(addr) 53 | const account = await client.getAccount(addr) 54 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 55 | const fee = { 56 | amount: [{ 57 | amount: "0.030000000000000000", 58 | denom: "okt", 59 | 60 | }], 61 | gas: "100000000", 62 | } 63 | 64 | const res = await client.updateFeeSplit(contractAddress,withdrawAddress, fee,sequence) 65 | console.log(JSON.stringify(res)) 66 | }) 67 | 68 | it("cancel feesplit ", async ()=> { 69 | jest.setTimeout(300000) 70 | const client = new OKEXChainClient(serverUrl, { 71 | chainId: "exchain-65", 72 | relativePath: "/okexchain-test/v1", 73 | isMainnet: false, 74 | }) 75 | 76 | await client.setAccountInfo(privateKey) 77 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 78 | console.log(addr) 79 | const account = await client.getAccount(addr) 80 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 81 | const fee = { 82 | amount: [{ 83 | amount: "0.030000000000000000", 84 | denom: "okt", 85 | 86 | }], 87 | gas: "100000000", 88 | } 89 | 90 | const res = await client.cancelFeeSplit(contractAddress, fee,sequence) 91 | console.log(JSON.stringify(res)) 92 | }) 93 | 94 | it("query feesplit ", async ()=> { 95 | jest.setTimeout(300000) 96 | const client = new OKEXChainClient(serverUrl, { 97 | chainId: "exchain-65", 98 | relativePath: "/okexchain-test/v1", 99 | isMainnet: false, 100 | }) 101 | 102 | const res = await client.queryFeesplit(contractAddress) 103 | console.log(JSON.stringify(res)) 104 | }) 105 | 106 | it("query DeployerFeeSplits ", async ()=> { 107 | jest.setTimeout(300000) 108 | const client = new OKEXChainClient(serverUrl, { 109 | chainId: "exchain-65", 110 | relativePath: "/okexchain-test/v1", 111 | isMainnet: false, 112 | }) 113 | const res = await client.queryDeployerFeeSplits(deployerAddress, 1, 100) 114 | console.log(JSON.stringify(res)) 115 | }) 116 | 117 | it("query WithdrawerFeeSplits ", async ()=> { 118 | jest.setTimeout(300000) 119 | const client = new OKEXChainClient(serverUrl, { 120 | chainId: "exchain-65", 121 | relativePath: "/okexchain-test/v1", 122 | isMainnet: false, 123 | }) 124 | 125 | const res = await client.queryWithdrawerFeeSplits(withdrawAddress, 1, 100) 126 | console.log(JSON.stringify(res)) 127 | }) 128 | 129 | }) 130 | -------------------------------------------------------------------------------- /__tests__/ibc.test.js: -------------------------------------------------------------------------------- 1 | import OKEXChainClient from "../src" 2 | import * as crypto from "../src/crypto" 3 | 4 | 5 | 6 | 7 | const serverUrl = "http://127.0.0.1:36659" 8 | 9 | 10 | const mnemonic = "giggle sibling fun arrow elevator spoon blood grocery laugh tortoise culture tool" 11 | 12 | 13 | 14 | describe("okc ibc test", async () => { 15 | it("ibc transfer test", async ()=> { 16 | 17 | const client = new OKEXChainClient(serverUrl, { 18 | chainId: "exchain-101", 19 | relativePath: "/exchain/v1", 20 | isMainnet: false 21 | }) 22 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '60') 23 | await client.setAccountInfo(privateKey) 24 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 25 | console.log(addr) 26 | const account = await client.getAccount(addr) 27 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 28 | const res = await client.ibcTransfer("cosmos1n064mg7jcxt2axur29mmek5ys7ghta4u4mhcjp", {amount: "2000000000000000000000", denom: "wei"}, "", "channel-0", "1","200000") 29 | console.log(JSON.stringify(res)) 30 | }) 31 | 32 | 33 | it("ibc query denom_traces", async () => { 34 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 35 | chainId: "ibc-1", 36 | relativePath: "/", 37 | isMainnet: false 38 | }) 39 | 40 | const res = await client.queryDenomTraces() 41 | console.log(JSON.stringify(res)) 42 | }) 43 | 44 | it("ibc query denom_trace", async () => { 45 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 46 | chainId: "ibc-1", 47 | relativePath: "/", 48 | isMainnet: false 49 | }) 50 | 51 | const res = await client.queryDenomTrace('CD3872E1E59BAA23BDAB04A829035D4988D6397569EC77F1DC991E4520D4092B') 52 | console.log(JSON.stringify(res)) 53 | }) 54 | 55 | it("ibc query parmas", async () => { 56 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 57 | chainId: "ibc-1", 58 | relativePath: "/", 59 | isMainnet: false 60 | }) 61 | 62 | const res = await client.queryIbcParams() 63 | console.log(JSON.stringify(res)) 64 | }) 65 | 66 | it("ibc query AllClientStates", async ()=> { 67 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 68 | chainId: "ibc-1", 69 | relativePath: "/", 70 | isMainnet: false 71 | }) 72 | const res = await client.queryAllClientStates() 73 | console.log(JSON.stringify(res)) 74 | }) 75 | 76 | it("ibc query clientState", async ()=> { 77 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 78 | chainId: "ibc-1", 79 | relativePath: "/", 80 | isMainnet: false 81 | }) 82 | const res = await client.queryClientStates('07-tendermint-0') 83 | console.log(JSON.stringify(res)) 84 | }) 85 | 86 | it( 'ibc query clientConnections', async ()=> { 87 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 88 | chainId: "ibc-1", 89 | relativePath: "/", 90 | isMainnet: false 91 | }) 92 | const res = await client.queryClientConnections('07-tendermint-0') 93 | console.log(JSON.stringify(res)) 94 | }) 95 | 96 | it( 'ibc query all connections', async ()=> { 97 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 98 | chainId: "ibc-1", 99 | relativePath: "/", 100 | isMainnet: false 101 | }) 102 | 103 | const res = await client.queryAllConnections() 104 | console.log(JSON.stringify(res)) 105 | }) 106 | 107 | it('ibc query connection', async ()=> { 108 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 109 | chainId: "ibc-1", 110 | relativePath: "/", 111 | isMainnet: false 112 | }) 113 | 114 | const res = await client.queryConnection('connection-0') 115 | console.log(JSON.stringify(res)) 116 | }) 117 | 118 | it('query all channels', async ()=> { 119 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 120 | chainId: "ibc-1", 121 | relativePath: "/", 122 | isMainnet: false 123 | }) 124 | 125 | const res = await client.queryAllChannels() 126 | console.log(JSON.stringify(res)) 127 | }) 128 | 129 | 130 | it('query channel', async ()=> { 131 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 132 | chainId: "ibc-1", 133 | relativePath: "/", 134 | isMainnet: false 135 | }) 136 | 137 | const res = await client.queryChannel('channel-0','transfer') 138 | console.log(JSON.stringify(res)) 139 | }) 140 | 141 | it('queryPacketCommitments', async ()=> { 142 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 143 | chainId: "ibc-1", 144 | relativePath: "/", 145 | isMainnet: false 146 | }) 147 | 148 | const res = await client.queryPacketCommitments('channel-0','transfer',0) 149 | console.log(JSON.stringify(res)) 150 | }) 151 | 152 | it('queryConnectionChannels', async ()=> { 153 | const client = new OKEXChainClient("http://127.0.0.1:10001", { 154 | chainId: "ibc-1", 155 | relativePath: "/", 156 | isMainnet: false 157 | }) 158 | 159 | const res = await client.queryConnectionChannels('connection-0') 160 | console.log(JSON.stringify(res)) 161 | }) 162 | 163 | it('query tx', async () => { 164 | const client = new OKEXChainClient("http://127.0.0.1:36659", { 165 | chainId: "exchain-101", 166 | relativePath: "/exchain/v1", 167 | isMainnet: false 168 | }) 169 | const res = await client.queryTx('D7702BCC93BC3CA3C16EB0F9B1F945D33D1860B931B78FDDB6F0517B120E5E91') 170 | console.log(JSON.stringify(res)) 171 | }) 172 | 173 | it('query txs', async ()=> { 174 | const client = new OKEXChainClient("http://127.0.0.1:36659",{ 175 | chainId: "exchain-101", 176 | relativePath: "/exchain/v1", 177 | isMainnet: false 178 | }) 179 | 180 | const res = await client.queryTxs({action: 'transfer', sender: 'ex1qj5c07sm6jetjz8f509qtrxgh4psxkv3ddyq7u'}) 181 | console.log(JSON.stringify(res)) 182 | }) 183 | 184 | it("query header", async ()=>{ 185 | const client = new OKEXChainClient("http://127.0.0.1:36659", { 186 | chainId: "exchain-101", 187 | relativePath: "/exchain/v1", 188 | isMainnet: false 189 | },"http://127.0.0.1:36657",) 190 | const res = await client.queryHeader(1) 191 | console.log(JSON.stringify(res)) 192 | }) 193 | }) -------------------------------------------------------------------------------- /__tests__/secp256k1wallet.test.js: -------------------------------------------------------------------------------- 1 | import {OKCSecp256k1Wallet} from "../lib"; 2 | import * as crypto from "../src/crypto"; 3 | 4 | 5 | describe("okc wasm test", function () { 6 | it("test wallet", async () => { 7 | const mnemonic = "giggle sibling fun arrow elevator spoon blood grocery laugh tortoise culture tool" 8 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '60') 9 | const wallet = await OKCSecp256k1Wallet.fromKey(privateKey) 10 | const accounts = await wallet.getAccounts() 11 | console.log(accounts[0].address); 12 | expect(accounts[0].address).toBe("0x945cC9CFFe7E16040b3f3ad267BBBdcab13a9Ed0") 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /__tests__/wasm.test.js: -------------------------------------------------------------------------------- 1 | import OKEXChainClient from "../src" 2 | import * as crypto from "../src/crypto" 3 | import { calculateFee, GasPrice } from "@cosmjs/stargate"; 4 | import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; 5 | import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; 6 | import {re} from "@babel/core/lib/vendor/import-meta-resolve"; 7 | 8 | const serverUrl = "http://127.0.0.1:8545" 9 | 10 | 11 | const mnemonic = "giggle sibling fun arrow elevator spoon blood grocery laugh tortoise culture tool" 12 | const addr = "ex1qj5c07sm6jetjz8f509qtrxgh4psxkv3ddyq7u" 13 | const mnemonic2 = "antique onion adult slot sad dizzy sure among cement demise submit scare" 14 | const addr2 = "ex1fsfwwvl93qv6r56jpu084hxxzn9zphnyxhske5" 15 | 16 | describe("okc wasm test", function() { 17 | 18 | it("store wasm code ", async ()=> { 19 | jest.setTimeout(300000) 20 | const client = new OKEXChainClient(serverUrl, { 21 | chainId: "exchain-67", 22 | relativePath: "/exchain/v1", 23 | isMainnet: false, 24 | }) 25 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '60') 26 | await client.setAccountInfo(privateKey) 27 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 28 | console.log(addr) 29 | const account = await client.getAccount(addr) 30 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 31 | const fee = { 32 | amount: [{ 33 | amount: "0.030000000000000000", 34 | denom: "okt", 35 | 36 | }], 37 | gas: "100000000", 38 | } 39 | 40 | 41 | // const permission = { 42 | // permission: "Nobody", 43 | // } 44 | // 45 | 46 | //default 47 | const permission = { 48 | permission: "Everybody", 49 | } 50 | 51 | // const permission = { 52 | // address: "ex1qj5c07sm6jetjz8f509qtrxgh4psxkv3ddyq7u", 53 | // permission: "OnlyAddress", 54 | // } 55 | 56 | const res = await client.storeCode("__tests__/wasm_contract/hackatom.wasm",permission, sequence,fee) 57 | console.log(JSON.stringify(res)) 58 | // await new Promise(resolve=>setTimeout(resolve, 1000)) 59 | 60 | // if (res.result.code == 0 ){ 61 | // const hash = res.result.data 62 | // console.log(hash) 63 | // const txRes = await client.queryTx(hash) 64 | // console.log(JSON.stringify(txRes)) 65 | // } 66 | 67 | }) 68 | 69 | it('query tx', async function () { 70 | const client = new OKEXChainClient(serverUrl, { 71 | chainId: "exchain-67", 72 | relativePath: "/exchain/v1", 73 | isMainnet: false, 74 | }) 75 | 76 | const res = await client.queryTx("58CF81F1C9F3FDBFD738A640BAC4D31A3BAF6B7A95EFB21B7890C99E81856F8B") 77 | console.log(JSON.stringify(res)) 78 | }); 79 | 80 | it("instantiate wasm contract ", async ()=> { 81 | 82 | const client = new OKEXChainClient(serverUrl, { 83 | chainId: "exchain-67", 84 | relativePath: "/exchain/v1", 85 | isMainnet: false, 86 | }) 87 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '60') 88 | await client.setAccountInfo(privateKey) 89 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 90 | console.log(addr) 91 | const account = await client.getAccount(addr) 92 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 93 | const fee = { 94 | amount: [{ 95 | amount: "0.030000000000000000", 96 | denom: "okt", 97 | 98 | }], 99 | gas: "100000000", 100 | } 101 | 102 | const initMsg = {"beneficiary": "ex1fsfwwvl93qv6r56jpu084hxxzn9zphnyxhske5", "verifier": "ex1qj5c07sm6jetjz8f509qtrxgh4psxkv3ddyq7u"} 103 | const amount = [{ 104 | amount: "1", 105 | denom: "okt", 106 | 107 | }] 108 | 109 | // const initMsg = {"purchase_price":{"amount":"1","denom":"okt"},"transfer_price":{"amount":"1","denom":"okt"}} 110 | const res = await client.instantiateContract("27","v1.0.0", initMsg, amount, "ex1qj5c07sm6jetjz8f509qtrxgh4psxkv3ddyq7u", fee,sequence) 111 | console.log(JSON.stringify(res)) 112 | }) 113 | 114 | it('execute contract',async function () { 115 | const client = new OKEXChainClient(serverUrl, { 116 | chainId: "exchain-67", 117 | relativePath: "/exchain/v1", 118 | isMainnet: false, 119 | }) 120 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '60') 121 | await client.setAccountInfo(privateKey) 122 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 123 | console.log(addr) 124 | const account = await client.getAccount(addr) 125 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 126 | const fee = { 127 | amount: [{ 128 | amount: "0.030000000000000000", 129 | denom: "okt", 130 | 131 | }], 132 | gas: "100000000", 133 | } 134 | const amount = [{ 135 | amount: "1", 136 | denom: "okt", 137 | 138 | }] 139 | 140 | let execMsg = {"release":{}} 141 | const res = await client.executeContract( "ex1efgvwhxkaj642uwjq65q9k3wzrghy0v2ftyap0kkwe4r3nx3846sjhluuc", execMsg,amount,fee,sequence) 142 | console.log(JSON.stringify(res)) 143 | }); 144 | 145 | it("store migrate wasm code ", async ()=> { 146 | 147 | const client = new OKEXChainClient(serverUrl, { 148 | chainId: "exchain-67", 149 | relativePath: "/exchain/v1", 150 | isMainnet: false, 151 | }) 152 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '60') 153 | await client.setAccountInfo(privateKey) 154 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 155 | console.log(addr) 156 | const account = await client.getAccount(addr) 157 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 158 | const fee = { 159 | amount: [{ 160 | amount: "0.030000000000000000", 161 | denom: "okt", 162 | 163 | }], 164 | gas: "100000000", 165 | } 166 | 167 | const permission = { 168 | permission: "Everybody", 169 | } 170 | const res = await client.storeCode("__tests__/wasm_contract/burner.wasm", permission,sequence,fee) 171 | console.log(JSON.stringify(res)) 172 | }) 173 | 174 | it('migrate contract', async function () { 175 | const client = new OKEXChainClient(serverUrl, { 176 | chainId: "exchain-67", 177 | relativePath: "/exchain/v1", 178 | isMainnet: false, 179 | }) 180 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '60') 181 | await client.setAccountInfo(privateKey) 182 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 183 | console.log(addr) 184 | const account = await client.getAccount(addr) 185 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 186 | const fee = { 187 | amount: [{ 188 | amount: "0.030000000000000000", 189 | denom: "okt", 190 | 191 | }], 192 | gas: "100000000", 193 | } 194 | 195 | const migrateMsg = {"payout": "ex1qj5c07sm6jetjz8f509qtrxgh4psxkv3ddyq7u"} 196 | const res = await client.migrateContract("3","ex1yw4xvtc43me9scqfr2jr2gzvcxd3a9y4eq7gaukreugw2yd2f8tsfem2z7",migrateMsg,fee, sequence) 197 | console.log(JSON.stringify(res)) 198 | }); 199 | 200 | it('update contract admin', async function () { 201 | const client = new OKEXChainClient(serverUrl, { 202 | chainId: "exchain-67", 203 | relativePath: "/exchain/v1", 204 | isMainnet: false, 205 | }) 206 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '60') 207 | await client.setAccountInfo(privateKey) 208 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 209 | console.log(addr) 210 | const account = await client.getAccount(addr) 211 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 212 | const fee = { 213 | amount: [{ 214 | amount: "0.030000000000000000", 215 | denom: "okt", 216 | 217 | }], 218 | gas: "100000000", 219 | } 220 | 221 | const res = await client.updateContractAdmin("ex1yw4xvtc43me9scqfr2jr2gzvcxd3a9y4eq7gaukreugw2yd2f8tsfem2z7", "ex1fsfwwvl93qv6r56jpu084hxxzn9zphnyxhske5",fee,sequence) 222 | console.log(JSON.stringify(res)) 223 | }); 224 | 225 | it('clear contract admin', async function () { 226 | const client = new OKEXChainClient(serverUrl, { 227 | chainId: "exchain-67", 228 | relativePath: "/exchain/v1", 229 | isMainnet: false, 230 | }) 231 | const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic2, '60') 232 | await client.setAccountInfo(privateKey) 233 | const addr = crypto.getAddressFromPrivateKey(client.privateKey) 234 | console.log(addr) 235 | const account = await client.getAccount(addr) 236 | const sequence = parseInt((await client.getSequenceNumberFromAccountInfo(account))) 237 | const fee = { 238 | amount: [{ 239 | amount: "0.030000000000000000", 240 | denom: "okt", 241 | 242 | }], 243 | gas: "100000000", 244 | } 245 | 246 | const res = await client.clearContractAdmin("ex1yw4xvtc43me9scqfr2jr2gzvcxd3a9y4eq7gaukreugw2yd2f8tsfem2z7", fee, sequence) 247 | console.log(JSON.stringify(res)) 248 | }); 249 | 250 | 251 | it('query list code', async function () { 252 | const client = new OKEXChainClient(serverUrl, { 253 | chainId: "exchain-67", 254 | relativePath: "/exchain/v1", 255 | isMainnet: false 256 | }) 257 | 258 | const res = await client.queryListCode() 259 | console.log(JSON.stringify(res)) 260 | }); 261 | 262 | it('query code', async function () { 263 | const client = new OKEXChainClient(serverUrl, { 264 | chainId: "exchain-67", 265 | relativePath: "/exchain/v1", 266 | isMainnet: false 267 | }) 268 | 269 | const res = await client.queryCode(1) 270 | console.log(JSON.stringify(res)) 271 | }); 272 | 273 | it('query list contracts', async function () { 274 | const client = new OKEXChainClient(serverUrl, { 275 | chainId: "exchain-67", 276 | relativePath: "/exchain/v1", 277 | isMainnet: false 278 | }) 279 | 280 | const res = await client.queryListContracts(27) 281 | console.log(JSON.stringify(res)) 282 | }); 283 | 284 | it('query contract', async function () { 285 | const client = new OKEXChainClient(serverUrl, { 286 | chainId: "exchain-67", 287 | relativePath: "/exchain/v1", 288 | isMainnet: false 289 | }) 290 | 291 | const res = await client.queryContract("ex1efgvwhxkaj642uwjq65q9k3wzrghy0v2ftyap0kkwe4r3nx3846sjhluuc") 292 | console.log(JSON.stringify(res)) 293 | }); 294 | 295 | it('query contract history', async function () { 296 | const client = new OKEXChainClient(serverUrl, { 297 | chainId: "exchain-67", 298 | relativePath: "/exchain/v1", 299 | isMainnet: false 300 | }) 301 | 302 | const res = await client.queryContractHistory("ex1efgvwhxkaj642uwjq65q9k3wzrghy0v2ftyap0kkwe4r3nx3846sjhluuc") 303 | console.log(JSON.stringify(res)) 304 | }); 305 | 306 | it('query contract state all', async function () { 307 | const client = new OKEXChainClient(serverUrl, { 308 | chainId: "exchain-67", 309 | relativePath: "/exchain/v1", 310 | isMainnet: false 311 | }) 312 | 313 | const res = await client.queryContractStateAll("ex1efgvwhxkaj642uwjq65q9k3wzrghy0v2ftyap0kkwe4r3nx3846sjhluuc") 314 | console.log(JSON.stringify(res)) 315 | }); 316 | 317 | it('query contract state smart', async function () { 318 | const client = new OKEXChainClient(serverUrl, { 319 | chainId: "exchain-67", 320 | relativePath: "/exchain/v1", 321 | isMainnet: false 322 | }) 323 | 324 | const res = await client.queryContractStateSmart("ex1efgvwhxkaj642uwjq65q9k3wzrghy0v2ftyap0kkwe4r3nx3846sjhluuc",'{"verifier":{}}') 325 | console.log(JSON.stringify(res)) 326 | }); 327 | 328 | it('query contract state raw', async function () { 329 | const client = new OKEXChainClient(serverUrl, { 330 | chainId: "exchain-67", 331 | relativePath: "/exchain/v1", 332 | isMainnet: false 333 | }) 334 | 335 | const res = await client.queryContractStateRaw("ex1efgvwhxkaj642uwjq65q9k3wzrghy0v2ftyap0kkwe4r3nx3846sjhluuc",'config') 336 | console.log(JSON.stringify(res)) 337 | }); 338 | 339 | }) 340 | -------------------------------------------------------------------------------- /__tests__/wasm_contract/burner.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/okx/exchain-javascript-sdk/6df13eedee6660fcac0145197ec6508b8d425876/__tests__/wasm_contract/burner.wasm -------------------------------------------------------------------------------- /__tests__/wasm_contract/hackatom.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/okx/exchain-javascript-sdk/6df13eedee6660fcac0145197ec6508b8d425876/__tests__/wasm_contract/hackatom.wasm -------------------------------------------------------------------------------- /docs/okexchain-jssdk-doc-client.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## client 4 | 5 | * [client](#module_client) 6 | * [.OKEXChainClient](#module_client.OKEXChainClient) 7 | * [new exports.OKEXChainClient(url, config)](#new_module_client.OKEXChainClient_new) 8 | * [.setMode(mode)](#module_client.OKEXChainClient+setMode) 9 | * [.setChainId(id)](#module_client.OKEXChainClient+setChainId) 10 | * [.setAddress(address)](#module_client.OKEXChainClient+setAddress) 11 | * [.setAccountInfo(privateKey)](#module_client.OKEXChainClient+setAccountInfo) ⇒ OKEXChainClient 12 | * [.sendSendTransaction(to, amount, denom, memo, sequenceNumber)](#module_client.OKEXChainClient+sendSendTransaction) ⇒ Object 13 | * [.sendCancelOrderTransaction(orderId, memo, sequenceNumber)](#module_client.OKEXChainClient+sendCancelOrderTransaction) ⇒ Object 14 | * [.sendPlaceOrderTransaction(product, side, price, quantity, memo, sequence)](#module_client.OKEXChainClient+sendPlaceOrderTransaction) ⇒ Object 15 | * [.buildTransaction(msg, signMsg, memo, fee, sequenceNumber)](#module_client.OKEXChainClient+buildTransaction) ⇒ Transaction 16 | * [.sendTransaction(tx, mode)](#module_client.OKEXChainClient+sendTransaction) ⇒ Object 17 | * [.getAccount(address)](#module_client.OKEXChainClient+getAccount) ⇒ Object 18 | * [.getBalance(address)](#module_client.OKEXChainClient+getBalance) ⇒ Object 19 | * [.getBalanceFromAccountInfo(accountInfo)](#module_client.OKEXChainClient+getBalanceFromAccountInfo) ⇒ Object 20 | * [.getSequenceNumber(address)](#module_client.OKEXChainClient+getSequenceNumber) ⇒ Number 21 | * [.getSequenceNumberFromAccountInfo(accountInfo)](#module_client.OKEXChainClient+getSequenceNumberFromAccountInfo) ⇒ Number 22 | * [.getAccountNumberFromAccountInfo(accountInfo)](#module_client.OKEXChainClient+getAccountNumberFromAccountInfo) ⇒ Number 23 | * [.sendTokenIssueTransaction(symbol, whole_name, total_supply, mintable, description, memo, sequenceNumber)](#module_client.OKEXChainClient+sendTokenIssueTransaction) ⇒ Object 24 | * [.sendTokenBurnTransaction(token, amount, memo, sequenceNumber)](#module_client.OKEXChainClient+sendTokenBurnTransaction) ⇒ Object 25 | * [.sendTokenMintTransaction(token, amount, memo, sequenceNumber)](#module_client.OKEXChainClient+sendTokenMintTransaction) ⇒ Object 26 | * [.sendRegisterDexOperatorTransaction(website, handling_fee_address, memo, sequenceNumber)](#module_client.OKEXChainClient+sendRegisterDexOperatorTransaction) ⇒ Object 27 | * [.sendListTokenPairTransaction(base_asset, quote_asset, init_price, memo, sequenceNumber)](#module_client.OKEXChainClient+sendListTokenPairTransaction) ⇒ Object 28 | * [.sendAddProductDepositTransaction(amount, product, memo, sequenceNumber)](#module_client.OKEXChainClient+sendAddProductDepositTransaction) ⇒ Object 29 | * [.sendWithdrawProductDepositTransaction(amount, product, memo, sequenceNumber)](#module_client.OKEXChainClient+sendWithdrawProductDepositTransaction) ⇒ Object 30 | * [.sendAddLiquidityTransaction(min_liquidity, max_base_amount, base_token, quote_amount, quote_token, deadline, memo, sequenceNumber)](#module_client.OKEXChainClient+sendAddLiquidityTransaction) ⇒ Object 31 | * [.sendRemoveLiquidityTransaction(liquidity, min_base_amount, base_token, min_quote_amount, quote_token, deadline, memo, sequenceNumber)](#module_client.OKEXChainClient+sendRemoveLiquidityTransaction) ⇒ Object 32 | * [.sendCreateExchangeTransaction(Token0Name, Token1Name, memo, sequenceNumber)](#module_client.OKEXChainClient+sendCreateExchangeTransaction) ⇒ Object 33 | * [.sendSwapTokenTransaction(sold_token_amount, sold_token, min_bought_token_amount, bought_token, deadline, recipient, memo, sequenceNumber)](#module_client.OKEXChainClient+sendSwapTokenTransaction) ⇒ Object 34 | * [.sendFarmCreatePoolTransaction(pool_name, min_lock_denom, min_lock_amount, yield_symbol, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmCreatePoolTransaction) ⇒ Object 35 | * [.sendFarmDestroyPoolTransaction(pool_name, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmDestroyPoolTransaction) ⇒ Object 36 | * [.sendFarmProvideTransaction(pool_name, provide_denom, provide_amount, yielded_per_block, start_height, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmProvideTransaction) ⇒ Object 37 | * [.sendFarmLockTransaction(pool_name, lock_denom, lock_amount, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmLockTransaction) ⇒ Object 38 | * [.sendFarmUnLockTransaction(pool_name, unlock_denom, unlock_amount, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmUnLockTransaction) ⇒ Object 39 | * [.sendFarmClaimTransaction(pool_name, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmClaimTransaction) ⇒ Object 40 | * [.ibcTransfer(to, amount, denom, memo , sequenceNumber, isPrivatekeyOldAddress)](#module_client.OKEXChainClient+ibcTransfer) ⇒ Object 41 | 42 | 43 | 44 | ### client.OKEXChainClient 45 | The OKEXChain client. 46 | 47 | **Kind**: static class of [client](#module_client) 48 | 49 | * [.OKEXChainClient](#module_client.OKEXChainClient) 50 | * [new exports.OKEXChainClient(url, config)](#new_module_client.OKEXChainClient_new) 51 | * [.setMode(mode)](#module_client.OKEXChainClient+setMode) 52 | * [.setChainId(id)](#module_client.OKEXChainClient+setChainId) 53 | * [.setAddress(address)](#module_client.OKEXChainClient+setAddress) 54 | * [.setAccountInfo(privateKey)](#module_client.OKEXChainClient+setAccountInfo) ⇒ OKEXChainClient 55 | * [.sendSendTransaction(to, amount, denom, memo, sequenceNumber)](#module_client.OKEXChainClient+sendSendTransaction) ⇒ Object 56 | * [.sendCancelOrderTransaction(orderId, memo, sequenceNumber)](#module_client.OKEXChainClient+sendCancelOrderTransaction) ⇒ Object 57 | * [.sendPlaceOrderTransaction(product, side, price, quantity, memo, sequence)](#module_client.OKEXChainClient+sendPlaceOrderTransaction) ⇒ Object 58 | * [.buildTransaction(msg, signMsg, memo, fee, sequenceNumber)](#module_client.OKEXChainClient+buildTransaction) ⇒ Transaction 59 | * [.sendTransaction(tx, mode)](#module_client.OKEXChainClient+sendTransaction) ⇒ Object 60 | * [.getAccount(address)](#module_client.OKEXChainClient+getAccount) ⇒ Object 61 | * [.getBalance(address)](#module_client.OKEXChainClient+getBalance) ⇒ Object 62 | * [.getBalanceFromAccountInfo(accountInfo)](#module_client.OKEXChainClient+getBalanceFromAccountInfo) ⇒ Object 63 | * [.getSequenceNumber(address)](#module_client.OKEXChainClient+getSequenceNumber) ⇒ Number 64 | * [.getSequenceNumberFromAccountInfo(accountInfo)](#module_client.OKEXChainClient+getSequenceNumberFromAccountInfo) ⇒ Number 65 | * [.getAccountNumberFromAccountInfo(accountInfo)](#module_client.OKEXChainClient+getAccountNumberFromAccountInfo) ⇒ Number 66 | * [.sendTokenIssueTransaction(symbol, whole_name, total_supply, mintable, description, memo, sequenceNumber)](#module_client.OKEXChainClient+sendTokenIssueTransaction) ⇒ Object 67 | * [.sendTokenBurnTransaction(token, amount, memo, sequenceNumber)](#module_client.OKEXChainClient+sendTokenBurnTransaction) ⇒ Object 68 | * [.sendTokenMintTransaction(token, amount, memo, sequenceNumber)](#module_client.OKEXChainClient+sendTokenMintTransaction) ⇒ Object 69 | * [.sendRegisterDexOperatorTransaction(website, handling_fee_address, memo, sequenceNumber)](#module_client.OKEXChainClient+sendRegisterDexOperatorTransaction) ⇒ Object 70 | * [.sendListTokenPairTransaction(base_asset, quote_asset, init_price, memo, sequenceNumber)](#module_client.OKEXChainClient+sendListTokenPairTransaction) ⇒ Object 71 | * [.sendAddProductDepositTransaction(amount, product, memo, sequenceNumber)](#module_client.OKEXChainClient+sendAddProductDepositTransaction) ⇒ Object 72 | * [.sendWithdrawProductDepositTransaction(amount, product, memo, sequenceNumber)](#module_client.OKEXChainClient+sendWithdrawProductDepositTransaction) ⇒ Object 73 | * [.sendAddLiquidityTransaction(min_liquidity, max_base_amount, base_token, quote_amount, quote_token, deadline, memo, sequenceNumber)](#module_client.OKEXChainClient+sendAddLiquidityTransaction) ⇒ Object 74 | * [.sendRemoveLiquidityTransaction(liquidity, min_base_amount, base_token, min_quote_amount, quote_token, deadline, memo, sequenceNumber)](#module_client.OKEXChainClient+sendRemoveLiquidityTransaction) ⇒ Object 75 | * [.sendCreateExchangeTransaction(Token0Name, Token1Name, memo, sequenceNumber)](#module_client.OKEXChainClient+sendCreateExchangeTransaction) ⇒ Object 76 | * [.sendSwapTokenTransaction(sold_token_amount, sold_token, min_bought_token_amount, bought_token, deadline, recipient, memo, sequenceNumber)](#module_client.OKEXChainClient+sendSwapTokenTransaction) ⇒ Object 77 | * [.sendFarmCreatePoolTransaction(pool_name, min_lock_denom, min_lock_amount, yield_symbol, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmCreatePoolTransaction) ⇒ Object 78 | * [.sendFarmDestroyPoolTransaction(pool_name, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmDestroyPoolTransaction) ⇒ Object 79 | * [.sendFarmProvideTransaction(pool_name, provide_denom, provide_amount, yielded_per_block, start_height, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmProvideTransaction) ⇒ Object 80 | * [.sendFarmLockTransaction(pool_name, lock_denom, lock_amount, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmLockTransaction) ⇒ Object 81 | * [.sendFarmUnLockTransaction(pool_name, unlock_denom, unlock_amount, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmUnLockTransaction) ⇒ Object 82 | * [.sendFarmClaimTransaction(pool_name, memo, sequenceNumber)](#module_client.OKEXChainClient+sendFarmClaimTransaction) ⇒ Object 83 | [.ibcTransfer(receiver, token, memo, sourceChannel, revisionNumber, revisionHeight, isPrivatekeyOldAddress)]((#module_client.OKEXChainClient+ibcTransfer))⇒ Object 84 | 85 | 86 | 87 | 88 | 89 | #### new exports.OKEXChainClient(url, config) 90 | 91 | | Param | Type | Description | 92 | | --- | --- | --- | 93 | | url | string | | 94 | | config | Object | { chainId: "okexchain-66" (mainnet, default) / "okexchain-65" (testnet) relativePath: "/okexchain/v1" (mainnet, default) / "/okexchain-test/v1" (testnet) isMainnet: true (mainnet) / false (other, default) signer: external signer object, Object / null (default) } | 95 | 96 | 97 | 98 | #### okexChainClient.setMode(mode) 99 | set the mode when send transaction 100 | 101 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 102 | 103 | | Param | Type | Description | 104 | | --- | --- | --- | 105 | | mode | string | block|sync|async | 106 | 107 | 108 | 109 | #### okexChainClient.setChainId(id) 110 | set the chainId when send transaction 111 | 112 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 113 | 114 | | Param | Type | 115 | | --- | --- | 116 | | id | string | 117 | 118 | 119 | 120 | #### okexChainClient.setAddress(address) 121 | set the address 122 | 123 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 124 | 125 | | Param | Type | 126 | | --- | --- | 127 | | address | string | 128 | 129 | 130 | 131 | #### okexChainClient.setAccountInfo(privateKey) ⇒ OKEXChainClient 132 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 133 | 134 | | Param | Type | 135 | | --- | --- | 136 | | privateKey | string | 137 | 138 | 139 | 140 | #### okexChainClient.sendSendTransaction(to, amount, denom, memo, sequenceNumber) ⇒ Object 141 | Send SendTransaction. 142 | 143 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 144 | **Returns**: Object - response 145 | 146 | | Param | Type | Default | Description | 147 | | --- | --- | --- | --- | 148 | | to | String | | To Address | 149 | | amount | Number | | Coin Quantity | 150 | | denom | String | | Coin Name | 151 | | memo | String | | | 152 | | sequenceNumber | Number | | | 153 | 154 | 155 | 156 | #### okexChainClient.sendCancelOrderTransaction(orderId, memo, sequenceNumber) ⇒ Object 157 | Send CancelOrderTransaction. 158 | 159 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 160 | **Returns**: Object - response 161 | 162 | | Param | Type | Default | 163 | | --- | --- | --- | 164 | | orderId | String | | 165 | | memo | String | | 166 | | sequenceNumber | Number | | 167 | 168 | 169 | 170 | #### okexChainClient.sendPlaceOrderTransaction(product, side, price, quantity, memo, sequence) ⇒ Object 171 | Send PlaceOrderTransaction. 172 | 173 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 174 | **Returns**: Object - response 175 | 176 | | Param | Type | Default | 177 | | --- | --- | --- | 178 | | product | String | | 179 | | side | String | | 180 | | price | Number | | 181 | | quantity | Number | | 182 | | memo | Number | | 183 | | sequence | Number | | 184 | 185 | 186 | 187 | #### okexChainClient.buildTransaction(msg, signMsg, memo, fee, sequenceNumber) ⇒ Transaction 188 | Build Transaction for sending to okexchain. 189 | 190 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 191 | **Returns**: Transaction - Transaction object 192 | 193 | | Param | Type | Default | 194 | | --- | --- | --- | 195 | | msg | Object | | 196 | | signMsg | Object | | 197 | | memo | String | | 198 | | fee | String | | 199 | | sequenceNumber | Number | | 200 | 201 | 202 | 203 | #### okexChainClient.sendTransaction(tx, mode) ⇒ Object 204 | send transaction to OKEXChain. 205 | 206 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 207 | **Returns**: Object - response (success or fail) 208 | 209 | | Param | Type | Description | 210 | | --- | --- | --- | 211 | | tx | signedTx | signed Transaction object | 212 | | mode | Boolean | use synchronous mode, optional | 213 | 214 | 215 | 216 | #### okexChainClient.getAccount(address) ⇒ Object 217 | get account 218 | 219 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 220 | **Returns**: Object - result 221 | 222 | | Param | Type | 223 | | --- | --- | 224 | | address | String | 225 | 226 | 227 | 228 | #### okexChainClient.getBalance(address) ⇒ Object 229 | get balances from OKEXChain 230 | 231 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 232 | **Returns**: Object - result 233 | 234 | | Param | Type | 235 | | --- | --- | 236 | | address | String | 237 | 238 | 239 | 240 | #### okexChainClient.getBalanceFromAccountInfo(accountInfo) ⇒ Object 241 | get balances from accountInfo Object 242 | 243 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 244 | **Returns**: Object - result 245 | 246 | | Param | Type | Description | 247 | | --- | --- | --- | 248 | | accountInfo | Object | optional address | 249 | 250 | 251 | 252 | #### okexChainClient.getSequenceNumber(address) ⇒ Number 253 | get SequenceNumber from OKEXChain 254 | 255 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 256 | **Returns**: Number - sequenceNumber 257 | 258 | | Param | Type | 259 | | --- | --- | 260 | | address | String | 261 | 262 | 263 | 264 | #### okexChainClient.getSequenceNumberFromAccountInfo(accountInfo) ⇒ Number 265 | get SequenceNumber from accountInfo Object 266 | 267 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 268 | **Returns**: Number - sequenceNumber 269 | 270 | | Param | Type | 271 | | --- | --- | 272 | | accountInfo | String | 273 | 274 | 275 | 276 | #### okexChainClient.getAccountNumberFromAccountInfo(accountInfo) ⇒ Number 277 | get accountNumber from accountInfo Object 278 | 279 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 280 | **Returns**: Number - accountNumber 281 | 282 | | Param | Type | 283 | | --- | --- | 284 | | accountInfo | String | 285 | 286 | 287 | 288 | #### okexChainClient.sendTokenIssueTransaction(symbol, whole_name, total_supply, mintable, description, memo, sequenceNumber) ⇒ Object 289 | Send TokenIssueTransaction. 290 | 291 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 292 | **Returns**: Object - response 293 | 294 | | Param | Type | Default | 295 | | --- | --- | --- | 296 | | symbol | String | | 297 | | whole_name | String | | 298 | | total_supply | String | | 299 | | mintable | Boolean | false | 300 | | description | String | | 301 | | memo | String | | 302 | | sequenceNumber | Number | | 303 | 304 | 305 | 306 | #### okexChainClient.sendTokenBurnTransaction(token, amount, memo, sequenceNumber) ⇒ Object 307 | Send TokenBurnTransaction. 308 | 309 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 310 | **Returns**: Object - response 311 | 312 | | Param | Type | Default | 313 | | --- | --- | --- | 314 | | token | String | | 315 | | amount | String | | 316 | | memo | String | | 317 | | sequenceNumber | Number | | 318 | 319 | 320 | 321 | #### okexChainClient.sendTokenMintTransaction(token, amount, memo, sequenceNumber) ⇒ Object 322 | Send TokenMintTransaction. 323 | 324 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 325 | **Returns**: Object - response 326 | 327 | | Param | Type | Default | 328 | | --- | --- | --- | 329 | | token | String | | 330 | | amount | String | | 331 | | memo | String | | 332 | | sequenceNumber | Number | | 333 | 334 | 335 | 336 | #### okexChainClient.sendRegisterDexOperatorTransaction(website, handling_fee_address, memo, sequenceNumber) ⇒ Object 337 | Send RegisterDexOperatorTransaction. 338 | 339 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 340 | **Returns**: Object - response 341 | 342 | | Param | Type | Default | 343 | | --- | --- | --- | 344 | | website | String | | 345 | | handling_fee_address | String | | 346 | | memo | String | | 347 | | sequenceNumber | Number | | 348 | 349 | 350 | 351 | #### okexChainClient.sendListTokenPairTransaction(base_asset, quote_asset, init_price, memo, sequenceNumber) ⇒ Object 352 | Send ListTokenPairTransaction. 353 | 354 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 355 | **Returns**: Object - response 356 | 357 | | Param | Type | Default | 358 | | --- | --- | --- | 359 | | base_asset | String | | 360 | | quote_asset | String | | 361 | | init_price | String | | 362 | | memo | String | | 363 | | sequenceNumber | Number | | 364 | 365 | 366 | 367 | #### okexChainClient.sendAddProductDepositTransaction(amount, product, memo, sequenceNumber) ⇒ Object 368 | Send AddProductDepositTransaction. 369 | 370 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 371 | **Returns**: Object - response 372 | 373 | | Param | Type | Default | 374 | | --- | --- | --- | 375 | | amount | String | | 376 | | product | String | | 377 | | memo | String | | 378 | | sequenceNumber | Number | | 379 | 380 | 381 | 382 | #### okexChainClient.sendWithdrawProductDepositTransaction(amount, product, memo, sequenceNumber) ⇒ Object 383 | Send WithdrawProductDepositTransaction. 384 | 385 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 386 | **Returns**: Object - response 387 | 388 | | Param | Type | Default | 389 | | --- | --- | --- | 390 | | amount | String | | 391 | | product | String | | 392 | | memo | String | | 393 | | sequenceNumber | Number | | 394 | 395 | 396 | 397 | #### okexChainClient.sendAddLiquidityTransaction(min_liquidity, max_base_amount, base_token, quote_amount, quote_token, deadline, memo, sequenceNumber) ⇒ Object 398 | Send AddLiquidityTransaction. 399 | 400 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 401 | **Returns**: Object - response 402 | 403 | | Param | Type | Default | 404 | | --- | --- | --- | 405 | | min_liquidity | Number | | 406 | | max_base_amount | Number | | 407 | | base_token | String | | 408 | | quote_amount | Number | | 409 | | quote_token | String | | 410 | | deadline | String | | 411 | | memo | String | | 412 | | sequenceNumber | Number | | 413 | 414 | 415 | 416 | #### okexChainClient.sendRemoveLiquidityTransaction(liquidity, min_base_amount, base_token, min_quote_amount, quote_token, deadline, memo, sequenceNumber) ⇒ Object 417 | Send RemoveLiquidityTransaction. 418 | 419 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 420 | **Returns**: Object - response 421 | 422 | | Param | Type | Default | 423 | | --- | --- | --- | 424 | | liquidity | Number | | 425 | | min_base_amount | Number | | 426 | | base_token | String | | 427 | | min_quote_amount | Number | | 428 | | quote_token | String | | 429 | | deadline | String | | 430 | | memo | String | | 431 | | sequenceNumber | Number | | 432 | 433 | 434 | 435 | #### okexChainClient.sendCreateExchangeTransaction(Token0Name, Token1Name, memo, sequenceNumber) ⇒ Object 436 | Send CreateExchangeTransaction. 437 | 438 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 439 | **Returns**: Object - response 440 | 441 | | Param | Type | Default | 442 | | --- | --- | --- | 443 | | Token0Name | String | | 444 | | Token1Name | String | | 445 | | memo | String | | 446 | | sequenceNumber | Number | | 447 | 448 | 449 | 450 | #### okexChainClient.sendSwapTokenTransaction(sold_token_amount, sold_token, min_bought_token_amount, bought_token, deadline, recipient, memo, sequenceNumber) ⇒ Object 451 | Send SwapTokenTransaction. 452 | 453 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 454 | **Returns**: Object - response 455 | 456 | | Param | Type | Default | 457 | | --- | --- | --- | 458 | | sold_token_amount | Number | | 459 | | sold_token | String | | 460 | | min_bought_token_amount | Number | | 461 | | bought_token | String | | 462 | | deadline | String | | 463 | | recipient | String | | 464 | | memo | String | | 465 | | sequenceNumber | Number | | 466 | 467 | 468 | 469 | #### okexChainClient.sendFarmCreatePoolTransaction(pool_name, min_lock_denom, min_lock_amount, yield_symbol, memo, sequenceNumber) ⇒ Object 470 | Send FarmCreatePoolTransaction. 471 | 472 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 473 | **Returns**: Object - response 474 | 475 | | Param | Type | Default | 476 | | --- | --- | --- | 477 | | pool_name | String | | 478 | | min_lock_denom | String | | 479 | | min_lock_amount | Number | | 480 | | yield_symbol | String | | 481 | | memo | String | | 482 | | sequenceNumber | Number | | 483 | 484 | 485 | 486 | #### okexChainClient.sendFarmDestroyPoolTransaction(pool_name, memo, sequenceNumber) ⇒ Object 487 | Send FarmDestroyPoolTransaction. 488 | 489 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 490 | **Returns**: Object - response 491 | 492 | | Param | Type | Default | 493 | | --- | --- | --- | 494 | | pool_name | String | | 495 | | memo | String | | 496 | | sequenceNumber | Number | | 497 | 498 | 499 | 500 | #### okexChainClient.sendFarmProvideTransaction(pool_name, provide_denom, provide_amount, yielded_per_block, start_height, memo, sequenceNumber) ⇒ Object 501 | Send FarmProvideTransaction. 502 | 503 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 504 | **Returns**: Object - response 505 | 506 | | Param | Type | Default | 507 | | --- | --- | --- | 508 | | pool_name | String | | 509 | | provide_denom | String | | 510 | | provide_amount | Number | | 511 | | yielded_per_block | Number | | 512 | | start_height | String | | 513 | | memo | String | | 514 | | sequenceNumber | Number | | 515 | 516 | 517 | 518 | #### okexChainClient.sendFarmLockTransaction(pool_name, lock_denom, lock_amount, memo, sequenceNumber) ⇒ Object 519 | Send FarmLockTransaction. 520 | 521 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 522 | **Returns**: Object - response 523 | 524 | | Param | Type | Default | 525 | | --- | --- | --- | 526 | | pool_name | String | | 527 | | lock_denom | String | | 528 | | lock_amount | Number | | 529 | | memo | String | | 530 | | sequenceNumber | Number | | 531 | 532 | 533 | 534 | #### okexChainClient.sendFarmUnLockTransaction(pool_name, unlock_denom, unlock_amount, memo, sequenceNumber) ⇒ Object 535 | Send FarmUnLockTransaction. 536 | 537 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 538 | **Returns**: Object - response 539 | 540 | | Param | Type | Default | 541 | | --- | --- | --- | 542 | | pool_name | String | | 543 | | unlock_denom | String | | 544 | | unlock_amount | Number | | 545 | | memo | String | | 546 | | sequenceNumber | Number | | 547 | 548 | 549 | 550 | #### okexChainClient.sendFarmClaimTransaction(pool_name, memo, sequenceNumber) ⇒ Object 551 | Send FarmClaimTransaction. 552 | 553 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 554 | **Returns**: Object - response 555 | 556 | | Param | Type | Default | 557 | | --- | --- | --- | 558 | | pool_name | String | | 559 | | memo | String | | 560 | | sequenceNumber | Number | | 561 | #### okexChainClient.ibcTransfer(receiver, token, memo, sourceChannel, revisionNumber, revisionHeight, isPrivatekeyOldAddress)⇒ Object 562 | ibcTransfer 563 | 564 | **Kind**: instance method of [OKEXChainClient](#module_client.OKEXChainClient) 565 | **Returns**: Object - response 566 | 567 | | Param | Type | Default | Remark | 568 | | --- | --- | --- | --- | 569 | | receiver | String | | | 570 | | Token | String | | | 571 | | sourceChannel | String | | | 572 | | revisionNumber | String | | The target chain-id, like "okc-100", typing "100" | 573 | | revisionHeight | String | | Timeout Height | 574 | | isPrivatekeyOldAddress | Number | 0 | | 575 | | memo | String | | | 576 | | | | | | 577 | 578 | -------------------------------------------------------------------------------- /docs/okexchain-jssdk-doc-crypto.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## crypto 4 | 5 | * [crypto](#module_crypto) 6 | * _static_ 7 | * [.getHDPath](#module_crypto.getHDPath) 8 | * [.decodeAddressToBuffer](#module_crypto.decodeAddressToBuffer) 9 | * [.validateAddress](#module_crypto.validateAddress) ⇒ boolean 10 | * [.encodeAddressToBech32](#module_crypto.encodeAddressToBech32) ⇒ string 11 | * [.convertBech32ToHex](#module_crypto.convertBech32ToHex) ⇒ String 12 | * [.convertHexToBech32](#module_crypto.convertHexToBech32) ⇒ string 13 | * [.generatePrivateKey](#module_crypto.generatePrivateKey) ⇒ string 14 | * [.getPubKeyFromHex](#module_crypto.getPubKeyFromHex) ⇒ Elliptic.PublicKey 15 | * [.encodePubKeyToCompressedBuffer](#module_crypto.encodePubKeyToCompressedBuffer) ⇒ Buffer 16 | * [.getPubKeyHexFromPrivateKey](#module_crypto.getPubKeyHexFromPrivateKey) ⇒ string 17 | * [.getPubKeyFromPrivateKey](#module_crypto.getPubKeyFromPrivateKey) ⇒ Elliptic.PublicKey 18 | * [.getAddressFromPubKey](#module_crypto.getAddressFromPubKey) ⇒ string 19 | * [.getAddressFromPrivateKey](#module_crypto.getAddressFromPrivateKey) ⇒ string 20 | * [.sign](#module_crypto.sign) ⇒ Buffer 21 | * [.validateSig](#module_crypto.validateSig) ⇒ boolean 22 | * [.generateKeyStore](#module_crypto.generateKeyStore) ⇒ object 23 | * [.getPrivateKeyFromKeyStore](#module_crypto.getPrivateKeyFromKeyStore) ⇒ string 24 | * [.generateMnemonic](#module_crypto.generateMnemonic) ⇒ string 25 | * [.validateMnemonic](#module_crypto.validateMnemonic) ⇒ bool 26 | * [.getPrivateKeyFromMnemonic](#module_crypto.getPrivateKeyFromMnemonic) ⇒ string 27 | * [.sha256Ripemd160](#module_crypto.sha256Ripemd160) ⇒ string 28 | * [.sha256](#module_crypto.sha256) ⇒ string 29 | * _inner_ 30 | * [~isBN(object)](#module_crypto..isBN) ⇒ Boolean 31 | * [~isHexStrict(hex)](#module_crypto..isHexStrict) ⇒ Boolean 32 | * [~sha3()](#module_crypto..sha3) ⇒ String 33 | * [~toChecksumAddress(address)](#module_crypto..toChecksumAddress) ⇒ String 34 | 35 | 36 | 37 | ### crypto.getHDPath 38 | Get HD path by cointype param . 39 | 40 | **Kind**: static constant of [crypto](#module_crypto) 41 | 42 | | Param | Type | Description | 43 | | --- | --- | --- | 44 | | cointype, | string | default 60 | 45 | 46 | 47 | 48 | ### crypto.decodeAddressToBuffer 49 | Decode address from bech32 to buffer. 50 | 51 | **Kind**: static constant of [crypto](#module_crypto) 52 | 53 | | Param | Type | Description | 54 | | --- | --- | --- | 55 | | addr | string | bech32 format | 56 | 57 | 58 | 59 | ### crypto.validateAddress ⇒ boolean 60 | Validate address. 61 | 62 | **Kind**: static constant of [crypto](#module_crypto) 63 | 64 | | Param | Type | Description | 65 | | --- | --- | --- | 66 | | addr | string | bech32 format | 67 | 68 | 69 | 70 | ### crypto.encodeAddressToBech32 ⇒ string 71 | Encodes address from hex to bech32 format. 72 | 73 | **Kind**: static constant of [crypto](#module_crypto) 74 | **Returns**: string - address with bech32 format 75 | 76 | | Param | Type | Description | 77 | | --- | --- | --- | 78 | | hexAddr | string | address in hex string | 79 | | prefix | string | address prefix | 80 | 81 | 82 | 83 | ### crypto.convertBech32ToHex ⇒ String 84 | covert ex address to 0x address 85 | 86 | **Kind**: static constant of [crypto](#module_crypto) 87 | 88 | | Param | 89 | | --- | 90 | | bech32Address | 91 | 92 | 93 | 94 | ### crypto.convertHexToBech32 ⇒ string 95 | covert 0x address to ex address 96 | 97 | **Kind**: static constant of [crypto](#module_crypto) 98 | 99 | | Param | 100 | | --- | 101 | | hexAddress | 102 | 103 | 104 | 105 | ### crypto.generatePrivateKey ⇒ string 106 | Generates privateKey. 107 | 108 | **Kind**: static constant of [crypto](#module_crypto) 109 | **Returns**: string - privateKey hex string 110 | 111 | | Param | Type | Description | 112 | | --- | --- | --- | 113 | | len | number | privateKey length (default: 32 bytes) | 114 | 115 | 116 | 117 | ### crypto.getPubKeyFromHex ⇒ Elliptic.PublicKey 118 | Get publicKey from hex string. 119 | 120 | **Kind**: static constant of [crypto](#module_crypto) 121 | **Returns**: Elliptic.PublicKey - pubKey 122 | 123 | | Param | Type | Description | 124 | | --- | --- | --- | 125 | | publicKey | string | pubKey with hex string format | 126 | 127 | 128 | 129 | ### crypto.encodePubKeyToCompressedBuffer ⇒ Buffer 130 | Encode pubKey to compressed pubKey buffer. 131 | 132 | **Kind**: static constant of [crypto](#module_crypto) 133 | 134 | | Param | Type | 135 | | --- | --- | 136 | | pubKey | Elliptic.PublicKey | 137 | 138 | 139 | 140 | ### crypto.getPubKeyHexFromPrivateKey ⇒ string 141 | Get public key from private key. 142 | 143 | **Kind**: static constant of [crypto](#module_crypto) 144 | **Returns**: string - public key in hex string 145 | 146 | | Param | Type | Description | 147 | | --- | --- | --- | 148 | | privateKeyHex | string | the private key hex string | 149 | 150 | 151 | 152 | ### crypto.getPubKeyFromPrivateKey ⇒ Elliptic.PublicKey 153 | Get public key from private key. 154 | 155 | **Kind**: static constant of [crypto](#module_crypto) 156 | **Returns**: Elliptic.PublicKey - PubKey 157 | 158 | | Param | Type | 159 | | --- | --- | 160 | | privateKey | Buffer | 161 | 162 | 163 | 164 | ### crypto.getAddressFromPubKey ⇒ string 165 | Gets address from pubKey with hex format. 166 | 167 | **Kind**: static constant of [crypto](#module_crypto) 168 | **Returns**: string - address 169 | 170 | | Param | Type | Description | 171 | | --- | --- | --- | 172 | | publicKey | string | publicKey hexstring | 173 | | prefix | string | address prefix | 174 | 175 | 176 | 177 | ### crypto.getAddressFromPrivateKey ⇒ string 178 | Get address from private key. 179 | 180 | **Kind**: static constant of [crypto](#module_crypto) 181 | **Returns**: string - address 182 | 183 | | Param | Type | Description | 184 | | --- | --- | --- | 185 | | privateKeyHex | string | the private key hexstring | 186 | | prefix | string | address prefix | 187 | 188 | 189 | 190 | ### crypto.sign ⇒ Buffer 191 | Sign msg with privateKey and Msg in hex format. 192 | 193 | **Kind**: static constant of [crypto](#module_crypto) 194 | **Returns**: Buffer - Signature. 195 | 196 | | Param | Type | Description | 197 | | --- | --- | --- | 198 | | msgHex | string | msg in hex format. | 199 | | privateKey | string | The private key in hex format. | 200 | 201 | 202 | 203 | ### crypto.validateSig ⇒ boolean 204 | Validate signature. 205 | 206 | **Kind**: static constant of [crypto](#module_crypto) 207 | 208 | | Param | Type | Description | 209 | | --- | --- | --- | 210 | | sigHex | string | signature in hex format | 211 | | msgHex | string | msg in hex format. | 212 | | pubKeyHex | string | public key in hex format | 213 | 214 | 215 | 216 | ### crypto.generateKeyStore ⇒ object 217 | Generate KeyStore with privateKey and password. 218 | 219 | **Kind**: static constant of [crypto](#module_crypto) 220 | 221 | | Param | Type | 222 | | --- | --- | 223 | | privateKeyHex | string | 224 | | password | string | 225 | 226 | 227 | 228 | ### crypto.getPrivateKeyFromKeyStore ⇒ string 229 | Get privateKey from keyStore. 230 | 231 | **Kind**: static constant of [crypto](#module_crypto) 232 | **Returns**: string - privateKey 233 | 234 | | Param | Type | 235 | | --- | --- | 236 | | keystore | string \| object | 237 | | password | string | 238 | 239 | 240 | 241 | ### crypto.generateMnemonic ⇒ string 242 | Generate mnemonic. 243 | 244 | **Kind**: static constant of [crypto](#module_crypto) 245 | 246 | 247 | ### crypto.validateMnemonic ⇒ bool 248 | Validate mnemonic. 249 | 250 | **Kind**: static constant of [crypto](#module_crypto) 251 | 252 | | Param | Type | 253 | | --- | --- | 254 | | mnemonic. | string | 255 | 256 | 257 | 258 | ### crypto.getPrivateKeyFromMnemonic ⇒ string 259 | Get private key from mnemonic. 260 | 261 | **Kind**: static constant of [crypto](#module_crypto) 262 | **Returns**: string - hexstring 263 | 264 | | Param | Type | Description | 265 | | --- | --- | --- | 266 | | mnemonic | string | | 267 | | cointype, | string | default 60 | 268 | 269 | 270 | 271 | ### crypto.sha256Ripemd160 ⇒ string 272 | Just like ripemd160(sha256(hex)) 273 | 274 | **Kind**: static constant of [crypto](#module_crypto) 275 | **Returns**: string - hash 276 | 277 | | Param | Type | 278 | | --- | --- | 279 | | hex | string | 280 | 281 | 282 | 283 | ### crypto.sha256 ⇒ string 284 | SHA256. 285 | 286 | **Kind**: static constant of [crypto](#module_crypto) 287 | **Returns**: string - hash 288 | 289 | | Param | Type | 290 | | --- | --- | 291 | | hex | string | 292 | 293 | 294 | 295 | ### crypto~isBN(object) ⇒ Boolean 296 | Returns true if object is BN, otherwise false 297 | 298 | **Kind**: inner method of [crypto](#module_crypto) 299 | 300 | | Param | Type | 301 | | --- | --- | 302 | | object | Object | 303 | 304 | 305 | 306 | ### crypto~isHexStrict(hex) ⇒ Boolean 307 | Check if string is HEX, requires a 0x in front 308 | 309 | **Kind**: inner method of [crypto](#module_crypto) 310 | 311 | | Param | Type | Description | 312 | | --- | --- | --- | 313 | | hex | String | to be checked | 314 | 315 | 316 | 317 | ### crypto~sha3() ⇒ String 318 | Hashes values to a sha3 hash using keccak 256 319 | 320 | To hash a HEX string the hex must have 0x in front. 321 | 322 | **Kind**: inner method of [crypto](#module_crypto) 323 | **Returns**: String - the sha3 string 324 | 325 | 326 | ### crypto~toChecksumAddress(address) ⇒ String 327 | Converts to a checksum address 328 | 329 | **Kind**: inner method of [crypto](#module_crypto) 330 | 331 | | Param | Type | Description | 332 | | --- | --- | --- | 333 | | address | String | the given HEX address | 334 | 335 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "testEnvironment": "node", 3 | testMatch: [ 4 | '**/*test.js?(x)', 5 | ], 6 | testPathIgnorePatterns: [ 7 | '/node_modules/', 8 | ], 9 | rootDir: '', 10 | moduleNameMapper: { 11 | '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 12 | '/__mocks__/fileMock.js', 13 | }, 14 | moduleFileExtensions: ['js','json','jsx','node'] 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@okexchain/javascript-sdk", 3 | "version": "1.7.1", 4 | "license": "Apache-2.0", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "cross-env NODE_ENV=test jest", 8 | "build": "rm -rf lib && npx babel src -d lib", 9 | "build:docsclient": "npx jsdoc-to-markdown -f src/client.js > docs/okexchain-jssdk-doc-client.md", 10 | "build:docscrypto": "npx jsdoc-to-markdown -f src/crypto/*.js > docs/okexchain-jssdk-doc-crypto.md", 11 | "prepublishOnly": "npm run build", 12 | "lint": "eslint --fix src __tests__", 13 | "sdk": "webpack-dev-server --config build/webpack.config.sdk.js" 14 | }, 15 | "dependencies": { 16 | "@cosmjs/amino": "^0.29.5", 17 | "@cosmjs/cosmwasm-stargate": "^0.29.0", 18 | "@cosmjs/crypto": "^0.29.5", 19 | "@cosmjs/proto-signing": "^0.29.0", 20 | "@cosmjs/stargate": "^0.29.0", 21 | "@walletconnect/client": "1.3.3", 22 | "axios": "^1.2.2", 23 | "babel-polyfill": "^6.26.0", 24 | "base32-encode": "^1.2.0", 25 | "bech32": "^1.1.4", 26 | "big.js": "^5.2.2", 27 | "bip32": "^1.0.2", 28 | "bip39": "^2.5.0", 29 | "bn.js": "^4.12.0", 30 | "camelcase": "^5.3.1", 31 | "crypto-browserify": "^3.12.0", 32 | "crypto-js": "^3.3.0", 33 | "eth-lib": "^0.1.29", 34 | "events": "^3.3.0", 35 | "is_js": "^0.9.0", 36 | "keccak": "^3.0.2", 37 | "lodash": "^4.17.21", 38 | "ndjson": "^1.5.0", 39 | "pako": "^2.0.4", 40 | "protocol-buffers-encodings": "^1.1.1", 41 | "pumpify": "^1.5.1", 42 | "safe-buffer": "^5.2.1", 43 | "schema": "^0.2.1", 44 | "secp256k1": "^4.0.3", 45 | "secure-random": "^1.1.2", 46 | "tiny-secp256k1": "^1.1.6", 47 | "url": "^0.11.0", 48 | "uuid": "^3.4.0", 49 | "varstruct": "^6.1.3", 50 | "web3": "^1.8.1", 51 | "websocket-stream": "^5.5.2" 52 | }, 53 | "devDependencies": { 54 | "@babel/cli": "^7.18.6", 55 | "@babel/core": "^7.18.6", 56 | "@babel/plugin-transform-async-to-generator": "^7.18.6", 57 | "@babel/preset-env": "^7.18.6", 58 | "@json-schema-spec/json-schema": "^0.1.3", 59 | "babel-core": "^7.0.0-0", 60 | "babel-eslint": "^10.1.0", 61 | "babel-jest": "^29.3.1", 62 | "babel-preset-stage-2": "^6.24.1", 63 | "browserify": "^16.5.2", 64 | "buffer": "^5.7.1", 65 | "cross-env": "^5.2.1", 66 | "eslint": "^5.11.1", 67 | "http-server": "^14.1.1", 68 | "husky": "^3.1.0", 69 | "jest": "^29.3.1", 70 | "jsdoc-to-markdown": "^8.0.0", 71 | "qunit": "^2.19.1" 72 | }, 73 | "babel": { 74 | "presets": [ 75 | "@babel/preset-env" 76 | ], 77 | "plugins": [ 78 | "@babel/plugin-transform-async-to-generator" 79 | ] 80 | }, 81 | "files": [ 82 | "lib/*" 83 | ] 84 | } 85 | -------------------------------------------------------------------------------- /src/client.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @jest-environment node 3 | */ 4 | /** 5 | * @module client 6 | */ 7 | import * as crypto from "./crypto" 8 | import Transaction from "./transaction" 9 | import HttpProxy from "./httpProxy" 10 | import RpcProxy from "./rpcProxy" 11 | import * as wallet from './wallet' 12 | 13 | 14 | import {int32} from "protocol-buffers-encodings"; 15 | 16 | const defaultChainId = "exchain-66" 17 | const defaultRelativePath = "/okexchain/v1" 18 | const mode = "block" 19 | const nativeDenom = "okt" 20 | const defaultTestnetFee = { 21 | amount: [{ 22 | amount: "0.000020000000000000", 23 | denom: nativeDenom, 24 | 25 | }], 26 | gas: "200000", 27 | } 28 | const defaultMainnetFee = { 29 | amount: [{ 30 | amount: "0.000020000000000000", 31 | denom: nativeDenom, 32 | 33 | }], 34 | gas: "200000", 35 | } 36 | 37 | 38 | const ibcFee = { 39 | amount: [{ 40 | amount: "0.030000000000000000", 41 | denom: "okt", 42 | 43 | }], 44 | gas: "2000000", 45 | } 46 | 47 | const denomHashUrl = '/ibc/apps/transfer/v1/denom_hashes' 48 | 49 | var defaultFee = defaultMainnetFee 50 | const precision = 18 51 | 52 | String.prototype.toBytes = function (encoding) { 53 | var bytes = []; 54 | var buff = new Buffer(this, encoding); 55 | for (var i = 0; i < buff.length; i++) { 56 | var byteint = buff[i]; 57 | bytes.push(byteint); 58 | } 59 | return bytes; 60 | } 61 | 62 | 63 | export const GetClient = async (privateKey, url) => { 64 | const client = new OKEXChainClient(url) 65 | client.setAccountInfo(privateKey) 66 | return client 67 | } 68 | 69 | /** 70 | * The OKEXChain client. 71 | */ 72 | export class OKEXChainClient { 73 | /** 74 | * @param {string} url 75 | * @param {Object} config 76 | * { 77 | * chainId: "exchain-66" (mainnet, default) / "exchain-65" (testnet) 78 | * relativePath: "/exchain/v1" (mainnet, default) / "/exchain-test/v1" (testnet) 79 | * isMainnet: true (mainnet) / false (other, default) 80 | * signer: external signer object, Object / null (default) 81 | * } 82 | */ 83 | constructor(url, config, rpcUrl = "127.0.0.1:26657") { 84 | if (!url) { 85 | throw new Error("null url") 86 | } 87 | this.httpClient = new HttpProxy(url) 88 | this.rpcClient = new RpcProxy(rpcUrl) 89 | this.mode = mode 90 | this.chainId = (config && config.chainId) || defaultChainId 91 | this.PostUrl = ((config && config.relativePath) || defaultRelativePath) + "/txs" 92 | this.queryAccountUrl = ((config && config.relativePath) || defaultRelativePath) + "/auth/accounts" 93 | this.isMainnet = (config && config.isMainnet) || false 94 | this.signer = (config && config.signer) || null 95 | this.restPrefix = config.relativePath 96 | 97 | if (this.isMainnet) { 98 | defaultFee = defaultMainnetFee 99 | } else { 100 | defaultFee = defaultTestnetFee 101 | } 102 | } 103 | 104 | /** 105 | * set the mode when send transaction 106 | * @param {string} mode block|sync|async 107 | */ 108 | async setMode(m) { 109 | this.mode = m 110 | } 111 | 112 | /** 113 | * set the chainId when send transaction 114 | * @param {string} id 115 | */ 116 | async setChainId(id) { 117 | this.chainId = id 118 | } 119 | 120 | /** 121 | * set the address 122 | * @param {string} address 123 | */ 124 | async setAddress(address) { 125 | if (address !== this.address) { 126 | this.address = address; 127 | const data = await this.getAccount(address); 128 | this.account_number = this.getAccountNumberFromAccountInfo(data); 129 | } 130 | 131 | return this 132 | } 133 | 134 | /** 135 | * @param {string} privateKey 136 | * @param {string} prefix 137 | * @return {OKEXChainClient} 138 | */ 139 | async setAccountInfo(privateKey, prefix = "ex", isPrivatekeyOld = 0) { 140 | if (!privateKey) { 141 | const address = await wallet.getAddress(); 142 | if (!address) throw new Error("invalid privateKey: " + privateKey) 143 | await this.setAccountInfoByWallet(address); 144 | return this; 145 | } 146 | if (privateKey !== this.privateKey) { 147 | let address = crypto.getAddressFromPrivateKey(privateKey, prefix) 148 | if (isPrivatekeyOld) { 149 | address = crypto.getAddressFromPrivateKeyLegacy(privateKey, prefix) 150 | } 151 | if (!address) throw new Error("invalid privateKey: " + privateKey) 152 | if (address === this.address) return this 153 | this.privateKey = privateKey 154 | this.address = address 155 | const data = await this.getAccount(address) 156 | this.account_number = this.getAccountNumberFromAccountInfo(data) 157 | } 158 | return this 159 | } 160 | 161 | /** 162 | * @return {OKEXChainClient} 163 | */ 164 | async setAccountInfoByWallet(address) { 165 | if (!address) throw new Error("invalid wallet connect address: " + address); 166 | if (address === this.address) return this 167 | this.address = address 168 | const data = await this.getAccount(address) 169 | this.account_number = this.getAccountNumberFromAccountInfo(data) 170 | return this 171 | } 172 | 173 | /** 174 | * Send SendTransaction. 175 | * @param {String} to To Address 176 | * @param {Number} amount Coin Quantity 177 | * @param {String} denom Coin Name 178 | * @param {String} memo 179 | * @param {Number} sequenceNumber 180 | * @return {Object} response 181 | */ 182 | 183 | async sendSendTransaction(to, amount, denom, memo = "", sequenceNumber = null, isPrivatekeyOldAddress = 0) { 184 | 185 | if (to.slice(0, 2) === '0x') { 186 | to = crypto.encodeAddressToBech32(to) 187 | } 188 | 189 | const coin = { 190 | amount: this.formatNumber(amount), 191 | denom: denom, 192 | 193 | } 194 | 195 | const msg = [{ 196 | type: "okexchain/token/MsgTransfer", 197 | value: { 198 | amount: [coin], 199 | from_address: this.address, 200 | to_address: to, 201 | }, 202 | }] 203 | 204 | const signMsg = msg 205 | 206 | 207 | const signedTx = await this.buildTransaction(msg, signMsg, memo, defaultFee, sequenceNumber, isPrivatekeyOldAddress) 208 | const res = await this.sendTransaction(signedTx) 209 | return res 210 | } 211 | 212 | /** 213 | * send ibc transfer transction 214 | * @param receiver 215 | * @param token 216 | * @param memo 217 | * @param sourceChannel 218 | * @param revisionNumber 219 | * @param revisionHeight 220 | * @param isPrivatekeyOldAddress 221 | * @returns {Promise<*>} 222 | */ 223 | async ibcTransfer(receiver, token, memo = "", sourceChannel, revisionNumber, revisionHeight, isPrivatekeyOldAddress = 0) { 224 | 225 | const msg = [{ 226 | type: "cosmos-sdk/MsgTransfer", 227 | value: { 228 | receiver: receiver, 229 | sender: this.address, 230 | source_channel: sourceChannel, 231 | source_port: "transfer", 232 | timeout_height: { 233 | revision_height: revisionHeight, 234 | revision_number: revisionNumber, 235 | }, 236 | token: token 237 | }, 238 | }] 239 | 240 | const signedTx = await this.buildTransaction(msg, msg, memo, ibcFee, 0, isPrivatekeyOldAddress) 241 | const res = await this.sendTransaction(signedTx) 242 | return res 243 | } 244 | 245 | /** 246 | * Send CancelOrderTransaction. 247 | * @param {String} orderId 248 | * @param {String} memo 249 | * @param {Number} sequenceNumber 250 | * @return {Object} response 251 | */ 252 | 253 | async sendCancelOrderTransaction(orderId, memo = "", sequenceNumber = null) { 254 | var orderIdList = [orderId] 255 | return this.sendCancelOrdersTransaction(orderIdList, memo, sequenceNumber) 256 | } 257 | 258 | async sendCancelOrdersTransaction(orderIdList, memo = "", sequenceNumber = null) { 259 | var msg = [] 260 | var signMsg = [] 261 | 262 | msg.push({ 263 | type: "okexchain/order/MsgCancel", 264 | value: { 265 | order_ids: orderIdList, 266 | sender: this.address, 267 | }, 268 | }) 269 | signMsg = msg 270 | 271 | const signedTx = await this.buildTransaction(msg, signMsg, memo, defaultFee, sequenceNumber) 272 | const res = await this.sendTransaction(signedTx) 273 | return res 274 | } 275 | 276 | /* 277 | * format number 278 | */ 279 | formatNumber(num) { 280 | let str = String(num); 281 | let retStr = ''; 282 | if (str.indexOf('.') >= 0) { 283 | if (str.split('.')[1].length > precision) { 284 | throw new Error("The actual received decimal precision is " + str.split('.')[1].length + ", and the expected is " + precision); 285 | } else if (str.split('.')[1].length == precision) { 286 | retStr = str 287 | } else { 288 | let appendix = ''; 289 | const len = precision - str.split('.')[1].length; 290 | for (let i = 0; i < len; i++) { 291 | appendix += '0'; 292 | } 293 | retStr = str + appendix; 294 | } 295 | } else { 296 | retStr += `${str}.000000000000000000`; 297 | } 298 | return retStr; 299 | }; 300 | 301 | /** 302 | * Send PlaceOrderTransaction. 303 | * @param {String} product 304 | * @param {String} side 305 | * @param {Number} price 306 | * @param {Number} quantity 307 | * @param {Number} memo 308 | * @param {Number} sequence 309 | * @return {Object} response 310 | */ 311 | async sendPlaceOrderTransaction(product, side, price, quantity, memo = "", sequence = null) { 312 | var order_items = [{ 313 | price: this.formatNumber(price), 314 | product: product, 315 | quantity: this.formatNumber(quantity), 316 | side: side, 317 | }] 318 | return this.sendPlaceOrdersTransaction(order_items, memo, sequence) 319 | } 320 | 321 | async sendPlaceOrdersTransaction(order_items, memo = "", sequence = null) { 322 | const placeOrderMsg = [{ 323 | type: "okexchain/order/MsgNew", 324 | value: { 325 | order_items: order_items, 326 | sender: this.address, 327 | }, 328 | 329 | }] 330 | const signMsg = placeOrderMsg 331 | 332 | 333 | const signedTx = await this.buildTransaction(placeOrderMsg, signMsg, memo, defaultFee, sequence) 334 | const res = await this.sendTransaction(signedTx) 335 | return res 336 | } 337 | 338 | /** 339 | * Build Transaction for sending to okexchain. 340 | * @param {Object} msg 341 | * @param {Object} signMsg 342 | * @param {String} memo 343 | * @param {String} fee 344 | * @param {Number} sequenceNumber 345 | * @return {Transaction} Transaction object 346 | */ 347 | async buildTransaction(msg, signMsg, memo = "", fee = null, sequenceNumber = null, isPrivatekeyOldAddress = 0) { 348 | if (!sequenceNumber) { 349 | const accountInfo = await this.getAccount() 350 | sequenceNumber = this.getSequenceNumberFromAccountInfo(accountInfo) 351 | this.account_number = this.getAccountNumberFromAccountInfo(accountInfo) 352 | } 353 | 354 | const params = { 355 | account_number: parseInt(this.account_number), 356 | chain_id: this.chainId, 357 | memo: memo, 358 | msg, 359 | sequence: sequenceNumber, 360 | fee: fee, 361 | } 362 | 363 | console.log(params) 364 | const tx = new Transaction(params) 365 | 366 | if (this.signer) { 367 | return await tx.sign(this.signer, signMsg, this.address); 368 | } else { 369 | return this.privateKey ? tx.sign(this.privateKey, signMsg, '', isPrivatekeyOldAddress) : tx.signByWallet(signMsg) 370 | } 371 | } 372 | 373 | /** 374 | * send transaction to OKEXChain. 375 | * @param {signedTx} tx signed Transaction object 376 | * @param {Boolean} mode use synchronous mode, optional 377 | * @return {Object} response (success or fail) 378 | */ 379 | async sendTransaction(signedTx) { 380 | const buf = signedTx.serializeTransactionWithJson(this.mode) 381 | console.log(buf) 382 | const opts = { 383 | data: buf, 384 | headers: { 385 | "content-type": "text/plain", 386 | } 387 | } 388 | return this.httpClient.send("post", this.PostUrl, null, opts) 389 | } 390 | 391 | 392 | /** 393 | * get account 394 | * @param {String} address 395 | * @return {Object} result 396 | */ 397 | async getAccount(address = this.address) { 398 | if (!address) { 399 | throw new Error("address should not be falsy") 400 | } 401 | try { 402 | console.log(`${this.queryAccountUrl}/${address}`) 403 | const data = await this.httpClient.send("get", `${this.queryAccountUrl}/${address}`) 404 | return data 405 | } catch (err) { 406 | return null 407 | } 408 | } 409 | 410 | /** 411 | * get balances from OKEXChain 412 | * @param {String} address 413 | * @return {Object} result 414 | */ 415 | async getBalance(address = this.address) { 416 | try { 417 | const data = await this.getAccount(address) 418 | return this.getBalanceFromAccountInfo(data) 419 | } catch (err) { 420 | return [] 421 | } 422 | } 423 | 424 | /** 425 | * get balances from accountInfo Object 426 | * @param {Object} accountInfo optional address 427 | * @return {Object} result 428 | */ 429 | async getBalanceFromAccountInfo(accountInfo) { 430 | return accountInfo.result.value.coins 431 | } 432 | 433 | /** 434 | * get SequenceNumber from OKEXChain 435 | * @param {String} address 436 | * @return {Number} sequenceNumber 437 | */ 438 | async getSequenceNumber(address = this.address) { 439 | try { 440 | const data = await this.getAccount(address) 441 | return this.getSequenceNumberFromAccountInfo(data) 442 | } catch (err) { 443 | return null 444 | } 445 | } 446 | 447 | /** 448 | * get SequenceNumber from accountInfo Object 449 | * @param {String} accountInfo 450 | * @return {Number} sequenceNumber 451 | */ 452 | getSequenceNumberFromAccountInfo(accountInfo) { 453 | return accountInfo.result.value.sequence 454 | } 455 | 456 | /** 457 | * get accountNumber from accountInfo Object 458 | * @param {String} accountInfo 459 | * @return {Number} accountNumber 460 | */ 461 | getAccountNumberFromAccountInfo(accountInfo) { 462 | console.log(accountInfo) 463 | return accountInfo.result.value.account_number 464 | } 465 | 466 | 467 | /** 468 | * Send TokenIssueTransaction. 469 | * @param {String} symbol 470 | * @param {String} whole_name 471 | * @param {String} total_supply 472 | * @param {Boolean} mintable 473 | * @param {String} description 474 | * @param {String} memo 475 | * @param {Number} sequenceNumber 476 | * @return {Object} response 477 | */ 478 | async sendTokenIssueTransaction(symbol, whole_name, total_supply, mintable = false, description = '', memo = '', sequenceNumber = null) { 479 | 480 | const msg = [{ 481 | type: "okexchain/token/MsgIssue", 482 | value: { 483 | description: description, 484 | mintable: mintable, 485 | original_symbol: symbol, 486 | owner: this.address, 487 | symbol: symbol, 488 | total_supply: total_supply, 489 | whole_name: whole_name, 490 | } 491 | }] 492 | 493 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 494 | const res = await this.sendTransaction(signedTx) 495 | return res 496 | } 497 | 498 | /** 499 | * Send TokenBurnTransaction. 500 | * @param {String} token 501 | * @param {String} amount 502 | * @param {String} memo 503 | * @param {Number} sequenceNumber 504 | * @return {Object} response 505 | */ 506 | async sendTokenBurnTransaction(token, amount, memo = "", sequenceNumber = null) { 507 | 508 | const msg = [{ 509 | type: "okexchain/token/MsgBurn", 510 | value: { 511 | amount: { 512 | amount: this.formatNumber(amount), 513 | denom: token 514 | }, 515 | owner: this.address 516 | } 517 | }] 518 | 519 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 520 | const res = await this.sendTransaction(signedTx) 521 | return res 522 | } 523 | 524 | /** 525 | * Send TokenMintTransaction. 526 | * @param {String} token 527 | * @param {String} amount 528 | * @param {String} memo 529 | * @param {Number} sequenceNumber 530 | * @return {Object} response 531 | */ 532 | async sendTokenMintTransaction(token, amount, memo = "", sequenceNumber = null) { 533 | 534 | const msg = [{ 535 | type: "okexchain/token/MsgMint", 536 | value: { 537 | amount: { 538 | amount: this.formatNumber(amount), 539 | denom: token 540 | }, 541 | owner: this.address 542 | } 543 | }] 544 | 545 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 546 | const res = await this.sendTransaction(signedTx) 547 | return res 548 | } 549 | 550 | /** 551 | * Send RegisterDexOperatorTransaction. 552 | * @param {String} website 553 | * @param {String} handling_fee_address 554 | * @param {String} memo 555 | * @param {Number} sequenceNumber 556 | * @return {Object} response 557 | */ 558 | 559 | async sendRegisterDexOperatorTransaction(website, handling_fee_address, memo = "", sequenceNumber = null) { 560 | 561 | if (!crypto.validateAddress(handling_fee_address)) { 562 | throw new Error("invalid handling_fee_address") 563 | } 564 | const msg = [{ 565 | type: "okexchain/dex/CreateOperator", 566 | value: { 567 | handling_fee_address: handling_fee_address, 568 | owner: this.address, 569 | website: website, 570 | }, 571 | }] 572 | 573 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 574 | const res = await this.sendTransaction(signedTx) 575 | return res 576 | } 577 | 578 | /** 579 | * Send ListTokenPairTransaction. 580 | * @param {String} base_asset 581 | * @param {String} quote_asset 582 | * @param {String} init_price 583 | * @param {String} memo 584 | * @param {Number} sequenceNumber 585 | * @return {Object} response 586 | */ 587 | 588 | async sendListTokenPairTransaction(base_asset, quote_asset, init_price, memo = "", sequenceNumber = null) { 589 | 590 | const msg = [{ 591 | type: "okexchain/dex/MsgList", 592 | value: { 593 | init_price: this.formatNumber(init_price), 594 | list_asset: base_asset, 595 | owner: this.address, 596 | quote_asset: quote_asset, 597 | }, 598 | }] 599 | 600 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 601 | const res = await this.sendTransaction(signedTx) 602 | return res 603 | } 604 | 605 | /** 606 | * Send AddProductDepositTransaction. 607 | * @param {String} amount 608 | * @param {String} product 609 | * @param {String} memo 610 | * @param {Number} sequenceNumber 611 | * @return {Object} response 612 | */ 613 | 614 | async sendAddProductDepositTransaction(amount, product, memo = "", sequenceNumber = null) { 615 | 616 | const coin = { 617 | amount: this.formatNumber(amount), 618 | denom: nativeDenom, 619 | } 620 | 621 | const msg = [{ 622 | type: "okexchain/dex/MsgDeposit", 623 | value: { 624 | amount: coin, 625 | depositor: this.address, 626 | product: product, 627 | }, 628 | }] 629 | 630 | 631 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 632 | const res = await this.sendTransaction(signedTx) 633 | return res 634 | } 635 | 636 | /** 637 | * Send WithdrawProductDepositTransaction. 638 | * @param {String} amount 639 | * @param {String} product 640 | * @param {String} memo 641 | * @param {Number} sequenceNumber 642 | * @return {Object} response 643 | */ 644 | 645 | async sendWithdrawProductDepositTransaction(amount, product, memo = "", sequenceNumber = null) { 646 | 647 | const coin = { 648 | amount: this.formatNumber(amount), 649 | denom: nativeDenom, 650 | } 651 | 652 | const msg = [{ 653 | type: "okexchain/dex/MsgWithdraw", 654 | value: { 655 | amount: coin, 656 | depositor: this.address, 657 | product: product, 658 | }, 659 | }] 660 | 661 | 662 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 663 | const res = await this.sendTransaction(signedTx) 664 | return res 665 | } 666 | 667 | /** 668 | * Send AddLiquidityTransaction. 669 | * @param {Number} min_liquidity 670 | * @param {Number} max_base_amount 671 | * @param {String} base_token 672 | * @param {Number} quote_amount 673 | * @param {String} quote_token 674 | * @param {String} deadline 675 | * @param {String} memo 676 | * @param {Number} sequenceNumber 677 | * @return {Object} response 678 | */ 679 | async sendAddLiquidityTransaction(min_liquidity, max_base_amount, base_token, quote_amount, quote_token, deadline, memo = '', sequenceNumber = null) { 680 | 681 | const base_coin = { 682 | amount: this.formatNumber(max_base_amount), 683 | denom: base_token, 684 | } 685 | const quote_coin = { 686 | amount: this.formatNumber(quote_amount), 687 | denom: quote_token, 688 | } 689 | 690 | const msg = [{ 691 | type: "okexchain/ammswap/MsgAddLiquidity", 692 | value: { 693 | deadline: deadline, 694 | max_base_amount: base_coin, 695 | min_liquidity: this.formatNumber(min_liquidity), 696 | quote_amount: quote_coin, 697 | sender: this.address, 698 | } 699 | }] 700 | 701 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 702 | const res = await this.sendTransaction(signedTx) 703 | return res 704 | } 705 | 706 | /** 707 | * Send RemoveLiquidityTransaction. 708 | * @param {Number} liquidity 709 | * @param {Number} min_base_amount 710 | * @param {String} base_token 711 | * @param {Number} min_quote_amount 712 | * @param {String} quote_token 713 | * @param {String} deadline 714 | * @param {String} memo 715 | * @param {Number} sequenceNumber 716 | * @return {Object} response 717 | */ 718 | async sendRemoveLiquidityTransaction(liquidity, min_base_amount, base_token, min_quote_amount, quote_token, deadline, memo = '', sequenceNumber = null) { 719 | 720 | const base_coin = { 721 | amount: this.formatNumber(min_base_amount), 722 | denom: base_token, 723 | } 724 | const quote_coin = { 725 | amount: this.formatNumber(min_quote_amount), 726 | denom: quote_token, 727 | } 728 | 729 | const msg = [{ 730 | type: "okexchain/ammswap/MsgRemoveLiquidity", 731 | value: { 732 | deadline: deadline, 733 | liquidity: this.formatNumber(liquidity), 734 | min_base_amount: base_coin, 735 | min_quote_amount: quote_coin, 736 | sender: this.address, 737 | } 738 | }] 739 | 740 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 741 | const res = await this.sendTransaction(signedTx) 742 | return res 743 | } 744 | 745 | /** 746 | * Send CreateExchangeTransaction. 747 | * @param {String} Token0Name 748 | * @param {String} Token1Name 749 | * @param {String} memo 750 | * @param {Number} sequenceNumber 751 | * @return {Object} response 752 | */ 753 | async sendCreateExchangeTransaction(Token0Name, Token1Name, memo = '', sequenceNumber = null) { 754 | 755 | const msg = [{ 756 | type: "okexchain/ammswap/MsgCreateExchange", 757 | value: { 758 | sender: this.address, 759 | token0_name: Token0Name, 760 | token1_name: Token1Name, 761 | } 762 | }] 763 | 764 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 765 | const res = await this.sendTransaction(signedTx) 766 | return res 767 | } 768 | 769 | /** 770 | * Send SwapTokenTransaction. 771 | * @param {Number} sold_token_amount 772 | * @param {String} sold_token 773 | * @param {Number} min_bought_token_amount 774 | * @param {String} bought_token 775 | * @param {String} deadline 776 | * @param {String} recipient 777 | * @param {String} memo 778 | * @param {Number} sequenceNumber 779 | * @return {Object} response 780 | */ 781 | async sendSwapTokenTransaction(sold_token_amount, sold_token, min_bought_token_amount, bought_token, deadline, recipient, memo = '', sequenceNumber = null) { 782 | 783 | const sold_coin = { 784 | amount: this.formatNumber(sold_token_amount), 785 | denom: sold_token, 786 | } 787 | const bought_coin = { 788 | amount: this.formatNumber(min_bought_token_amount), 789 | denom: bought_token, 790 | } 791 | 792 | const msg = [{ 793 | type: "okexchain/ammswap/MsgSwapToken", 794 | value: { 795 | deadline: deadline, 796 | min_bought_token_amount: bought_coin, 797 | recipient: recipient, 798 | sender: this.address, 799 | sold_token_amount: sold_coin, 800 | } 801 | }] 802 | 803 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 804 | const res = await this.sendTransaction(signedTx) 805 | return res 806 | } 807 | 808 | /** 809 | * Send FarmCreatePoolTransaction. 810 | * @param {String} pool_name 811 | * @param {String} min_lock_denom 812 | * @param {Number} min_lock_amount 813 | * @param {String} yield_symbol 814 | * @param {String} memo 815 | * @param {Number} sequenceNumber 816 | * @return {Object} response 817 | */ 818 | async sendFarmCreatePoolTransaction(pool_name, min_lock_denom, min_lock_amount, yield_symbol, memo = '', sequenceNumber = null) { 819 | const min_lock_coin = { 820 | amount: this.formatNumber(min_lock_amount), 821 | denom: min_lock_denom, 822 | } 823 | const msg = [{ 824 | type: "okexchain/farm/MsgCreatePool", 825 | value: { 826 | min_lock_amount: min_lock_coin, 827 | owner: this.address, 828 | pool_name: pool_name, 829 | yielded_symbol: yield_symbol, 830 | } 831 | }] 832 | 833 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 834 | const res = await this.sendTransaction(signedTx) 835 | return res 836 | } 837 | 838 | /** 839 | * Send FarmDestroyPoolTransaction. 840 | * @param {String} pool_name 841 | * @param {String} memo 842 | * @param {Number} sequenceNumber 843 | * @return {Object} response 844 | */ 845 | async sendFarmDestroyPoolTransaction(pool_name, memo = '', sequenceNumber = null) { 846 | const msg = [{ 847 | type: "okexchain/farm/MsgDestroyPool", 848 | value: { 849 | owner: this.address, 850 | pool_name: pool_name, 851 | } 852 | }] 853 | 854 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 855 | const res = await this.sendTransaction(signedTx) 856 | return res 857 | } 858 | 859 | /** 860 | * Send FarmProvideTransaction. 861 | * @param {String} pool_name 862 | * @param {String} provide_denom 863 | * @param {Number} provide_amount 864 | * @param {Number} yielded_per_block 865 | * @param {String} start_height 866 | * @param {String} memo 867 | * @param {Number} sequenceNumber 868 | * @return {Object} response 869 | */ 870 | async sendFarmProvideTransaction(pool_name, provide_denom, provide_amount, yielded_per_block, start_height, memo = '', sequenceNumber = null) { 871 | const provide_coin = { 872 | amount: this.formatNumber(provide_amount), 873 | denom: provide_denom, 874 | } 875 | const msg = [{ 876 | type: "okexchain/farm/MsgProvide", 877 | value: { 878 | address: this.address, 879 | amount: provide_coin, 880 | amount_yielded_per_block: this.formatNumber(yielded_per_block), 881 | pool_name: pool_name, 882 | start_height_to_yield: start_height, 883 | } 884 | }] 885 | 886 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 887 | const res = await this.sendTransaction(signedTx) 888 | return res 889 | } 890 | 891 | /** 892 | * Send FarmLockTransaction. 893 | * @param {String} pool_name 894 | * @param {String} lock_denom 895 | * @param {Number} lock_amount 896 | * @param {String} memo 897 | * @param {Number} sequenceNumber 898 | * @return {Object} response 899 | */ 900 | async sendFarmLockTransaction(pool_name, lock_denom, lock_amount, memo = '', sequenceNumber = null) { 901 | const amount = { 902 | amount: this.formatNumber(lock_amount), 903 | denom: lock_denom, 904 | } 905 | const msg = [{ 906 | type: "okexchain/farm/MsgLock", 907 | value: { 908 | address: this.address, 909 | amount: amount, 910 | pool_name: pool_name, 911 | } 912 | }] 913 | 914 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 915 | const res = await this.sendTransaction(signedTx) 916 | return res 917 | } 918 | 919 | /** 920 | * Send FarmUnLockTransaction. 921 | * @param {String} pool_name 922 | * @param {String} unlock_denom 923 | * @param {Number} unlock_amount 924 | * @param {String} memo 925 | * @param {Number} sequenceNumber 926 | * @return {Object} response 927 | */ 928 | async sendFarmUnLockTransaction(pool_name, unlock_denom, unlock_amount, memo = '', sequenceNumber = null) { 929 | const amount = { 930 | amount: this.formatNumber(unlock_amount), 931 | denom: unlock_denom, 932 | } 933 | const msg = [{ 934 | type: "okexchain/farm/MsgUnlock", 935 | value: { 936 | address: this.address, 937 | amount: amount, 938 | pool_name: pool_name, 939 | } 940 | }] 941 | 942 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 943 | const res = await this.sendTransaction(signedTx) 944 | return res 945 | } 946 | 947 | /** 948 | * Send FarmClaimTransaction. 949 | * @param {String} pool_name 950 | * @param {String} memo 951 | * @param {Number} sequenceNumber 952 | * @return {Object} response 953 | */ 954 | async sendFarmClaimTransaction(pool_name, memo = '', sequenceNumber = null) { 955 | const msg = [{ 956 | type: "okexchain/farm/MsgClaim", 957 | value: { 958 | address: this.address, 959 | pool_name: pool_name, 960 | } 961 | }] 962 | 963 | const signedTx = await this.buildTransaction(msg, msg, memo, defaultFee, sequenceNumber) 964 | const res = await this.sendTransaction(signedTx) 965 | return res 966 | } 967 | 968 | 969 | /** 970 | * store wasm code on the chain 971 | * @param wasmFile 972 | * @param permission 973 | * @param seqNo 974 | * @param fee 975 | * @returns {Promise<{result: *, status: *}|{result: {msg: string, code: number, detail_msg: string, data: string}, status: *}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}>} 976 | */ 977 | async storeCode(wasmFile, permission, seqNo, fee) { 978 | var fs = require("fs"); 979 | var pako = require("pako") 980 | const wasmCode = fs.readFileSync(wasmFile) 981 | const compressed = pako.gzip(wasmCode, {level: 9}); 982 | const msg = [{ 983 | type: "wasm/MsgStoreCode", 984 | value: { 985 | instantiate_permission: permission, 986 | sender: this.address, 987 | wasm_byte_code: Buffer.from(compressed).toString('base64'), 988 | } 989 | }] 990 | const signedTx = await this.buildTransaction(msg, msg, "store wasm code", fee, seqNo) 991 | console.log(signedTx) 992 | const res = await this.sendTransaction(signedTx) 993 | return res 994 | } 995 | 996 | /** 997 | * instantiate contract 998 | * @param codeId 999 | * @param label 1000 | * @param initMsg 1001 | * @param amount 1002 | * @param admin 1003 | * @param fee 1004 | * @param seqNo 1005 | * @returns {Promise<{result: *, status: *}|{result: {msg: string, code: number, detail_msg: string, data: string}, status: *}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}>} 1006 | */ 1007 | async instantiateContract(codeId, label, initMsg, amount, admin, fee, seqNo) { 1008 | const msg = [{ 1009 | type: "wasm/MsgInstantiateContract", 1010 | value: { 1011 | admin: admin, 1012 | code_id: codeId, 1013 | funds: amount, 1014 | label: label, 1015 | msg: initMsg, 1016 | sender: this.address, 1017 | } 1018 | }] 1019 | const signedTx = await this.buildTransaction(msg, msg, "instantiate wasm code", fee, seqNo) 1020 | const res = await this.sendTransaction(signedTx) 1021 | return res 1022 | } 1023 | 1024 | /** 1025 | * execute contract 1026 | * @param contractAddr 1027 | * @param execMsg 1028 | * @param amount 1029 | * @param fee 1030 | * @param seqNo 1031 | * @returns {Promise<{result: *, status: *}|{result: {msg: string, code: number, detail_msg: string, data: string}, status: *}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}>} 1032 | */ 1033 | async executeContract(contractAddr, execMsg, amount, fee, seqNo) { 1034 | const msg = [{ 1035 | type: "wasm/MsgExecuteContract", 1036 | value: { 1037 | contract: contractAddr, 1038 | funds: amount, 1039 | msg: execMsg, 1040 | sender: this.address, 1041 | } 1042 | }] 1043 | const signedTx = await this.buildTransaction(msg, msg, "execute contract", fee, seqNo) 1044 | const res = await this.sendTransaction(signedTx) 1045 | return res 1046 | } 1047 | 1048 | /** 1049 | * migrate contract 1050 | * @param codeId 1051 | * @param contractAddr 1052 | * @param migrateMsg 1053 | * @param fee 1054 | * @param seqNo 1055 | * @returns {Promise<{result: *, status: *}|{result: {msg: string, code: number, detail_msg: string, data: string}, status: *}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}>} 1056 | */ 1057 | async migrateContract(codeId, contractAddr, migrateMsg, fee, seqNo) { 1058 | const msg = [{ 1059 | type: "wasm/MsgMigrateContract", 1060 | value: { 1061 | code_id: codeId, 1062 | contract: contractAddr, 1063 | msg: migrateMsg, 1064 | sender: this.address, 1065 | } 1066 | }] 1067 | const signedTx = await this.buildTransaction(msg, msg, "migrate Contract ", fee, seqNo) 1068 | const res = await this.sendTransaction(signedTx) 1069 | return res 1070 | } 1071 | 1072 | 1073 | /** 1074 | * update contract admin 1075 | * @param contractAddr 1076 | * @param newAdminAddr 1077 | * @param fee 1078 | * @param seqNo 1079 | * @returns {Promise<{result: *, status: *}|{result: {msg: string, code: number, detail_msg: string, data: string}, status: *}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}>} 1080 | */ 1081 | async updateContractAdmin(contractAddr, newAdminAddr, fee, seqNo) { 1082 | const msg = [{ 1083 | type: "wasm/MsgUpdateAdmin", 1084 | value: { 1085 | contract: contractAddr, 1086 | new_admin: newAdminAddr, 1087 | sender: this.address, 1088 | } 1089 | }] 1090 | const signedTx = await this.buildTransaction(msg, msg, "update Contract Admin", fee, seqNo) 1091 | const res = await this.sendTransaction(signedTx) 1092 | return res 1093 | } 1094 | 1095 | /** 1096 | * clear contract admin 1097 | * @param contractAddr 1098 | * @param fee 1099 | * @param seqNo 1100 | * @returns {Promise<{result: *, status: *}|{result: {msg: string, code: number, detail_msg: string, data: string}, status: *}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}>} 1101 | */ 1102 | async clearContractAdmin(contractAddr, fee, seqNo) { 1103 | const msg = [{ 1104 | type: "wasm/MsgClearAdmin", 1105 | value: { 1106 | contract: contractAddr, 1107 | sender: this.address, 1108 | } 1109 | }] 1110 | const signedTx = await this.buildTransaction(msg, msg, "clear Contract Admin", fee, seqNo) 1111 | const res = await this.sendTransaction(signedTx) 1112 | return res 1113 | } 1114 | 1115 | 1116 | /** 1117 | * register FeeSplit 1118 | * @param contractAddress 1119 | * @param withdrawerAddress 1120 | * @param nonces 1121 | * @param fee 1122 | * @param seqNo 1123 | * @returns {Promise<{result: *, status: *}|{result: {msg: string, code: number, detail_msg: string, data: string}, status: *}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}>} 1124 | */ 1125 | async registerFeeSplit(contractAddress, withdrawerAddress, nonces, fee, seqNo) { 1126 | if (withdrawerAddress == '') { 1127 | withdrawerAddress = this.address 1128 | } 1129 | 1130 | const msg = [{ 1131 | type: "okexchain/MsgRegisterFeeSplit", 1132 | value: { 1133 | contract_address: contractAddress, 1134 | deployer_address: this.address, 1135 | nonces: nonces, 1136 | withdrawer_address: withdrawerAddress, 1137 | } 1138 | }] 1139 | const signedTx = await this.buildTransaction(msg, msg, "register feesplit", fee, seqNo) 1140 | const res = await this.sendTransaction(signedTx) 1141 | return res 1142 | } 1143 | 1144 | /** 1145 | * update FeeSplit 1146 | * @param contractAddress 1147 | * @param withdrawerAddress 1148 | * @param fee 1149 | * @param seqNo 1150 | * @returns {Promise<{result: *, status: *}|{result: {msg: string, code: number, detail_msg: string, data: string}, status: *}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}>} 1151 | */ 1152 | async updateFeeSplit(contractAddress, withdrawerAddress, fee, seqNo) { 1153 | if (withdrawerAddress == '') { 1154 | withdrawerAddress = this.address 1155 | } 1156 | 1157 | const msg = [{ 1158 | type: "okexchain/MsgUpdateFeeSplit", 1159 | value: { 1160 | contract_address: contractAddress, 1161 | deployer_address: this.address, 1162 | withdrawer_address: withdrawerAddress, 1163 | } 1164 | }] 1165 | const signedTx = await this.buildTransaction(msg, msg, "update feesplit", fee, seqNo) 1166 | const res = await this.sendTransaction(signedTx) 1167 | return res 1168 | } 1169 | 1170 | /** 1171 | * cancel FeeSplit 1172 | * @param contractAddress 1173 | * @param fee 1174 | * @param seqNo 1175 | * @returns {Promise<{result: *, status: *}|{result: {msg: string, code: number, detail_msg: string, data: string}, status: *}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}|{result: {msg, code: number, detail_msg: string, data: string}, status: number}>} 1176 | */ 1177 | async cancelFeeSplit(contractAddress, fee, seqNo) { 1178 | const msg = [{ 1179 | type: "okexchain/MsgCancelFeeSplit", 1180 | value: { 1181 | contract_address: contractAddress, 1182 | deployer_address: this.address, 1183 | } 1184 | }] 1185 | const signedTx = await this.buildTransaction(msg, msg, "cancel feesplit", fee, seqNo) 1186 | const res = await this.sendTransaction(signedTx) 1187 | return res 1188 | } 1189 | 1190 | async queryFeesplit(contractAddress) { 1191 | const url = this.restPrefix + '/feesplit/contract/'+contractAddress 1192 | const res = await this.httpClient.send("get", url) 1193 | return res 1194 | } 1195 | 1196 | async queryDeployerFeeSplits(deployerAddress, page, limit) { 1197 | const url = this.restPrefix + '/feesplit/deployer/'+deployerAddress + '?page='+page + '&limit='+limit 1198 | const res = await this.httpClient.send("get", url) 1199 | return res 1200 | } 1201 | 1202 | async queryWithdrawerFeeSplits(withdrawerAddress, page, limit) { 1203 | const url = this.restPrefix + '/feesplit/withdrawer/'+withdrawerAddress + '?page='+page + '&limit='+limit 1204 | const res = await this.httpClient.send("get", url) 1205 | return res 1206 | } 1207 | 1208 | async queryListCode() { 1209 | const url = this.restPrefix + '/wasm/code' 1210 | const res = await this.httpClient.send("get", url) 1211 | return res 1212 | } 1213 | 1214 | async queryCode(codeId) { 1215 | const url = this.restPrefix + '/wasm/code/' + codeId 1216 | const res = await this.httpClient.send("get", url) 1217 | return res 1218 | } 1219 | 1220 | async queryListContracts(codeId) { 1221 | const url = this.restPrefix + '/wasm/code/' + codeId + '/contracts' 1222 | const res = await this.httpClient.send("get", url) 1223 | return res 1224 | } 1225 | 1226 | async queryContract(contractAddr) { 1227 | const url = this.restPrefix + '/wasm/contract/' + contractAddr 1228 | const res = await this.httpClient.send("get", url) 1229 | return res 1230 | } 1231 | 1232 | async queryContractStateAll(contractAddr) { 1233 | const url = this.restPrefix + '/wasm/contract/' + contractAddr + '/state' 1234 | const res = await this.httpClient.send("get", url) 1235 | return res 1236 | } 1237 | 1238 | async queryContractHistory(contractAddr) { 1239 | const url = this.restPrefix + '/wasm/contract/' + contractAddr + '/history' 1240 | const res = await this.httpClient.send("get", url) 1241 | return res 1242 | } 1243 | 1244 | async queryContractStateSmart(contractAddr, query) { 1245 | const url = this.restPrefix + '/wasm/contract/' + contractAddr + '/smart/' + Buffer.from(query).toString("base64") + '?encoding=base64' 1246 | const res = await this.httpClient.send("get", url) 1247 | return res 1248 | } 1249 | 1250 | async queryContractStateRaw(contractAddr, key) { 1251 | const url = this.restPrefix + '/wasm/contract/' + contractAddr + '/raw/' + Buffer.from(key).toString("hex") + '?encoding=hex' 1252 | const res = await this.httpClient.send("get", url) 1253 | return res 1254 | } 1255 | 1256 | async queryDenomTraces() { 1257 | const url = '/ibc/apps/transfer/v1/denom_traces' 1258 | const res = await this.httpClient.send("get", url) 1259 | return res 1260 | } 1261 | 1262 | async queryDenomTrace(hash) { 1263 | const url = '/ibc/apps/transfer/v1/denom_traces/' + hash 1264 | const res = await this.httpClient.send("get", url) 1265 | return res 1266 | } 1267 | 1268 | async queryIbcParams() { 1269 | const url = '/ibc/apps/transfer/v1/params' 1270 | const res = await this.httpClient.send("get", url) 1271 | return res 1272 | } 1273 | 1274 | 1275 | async queryAllClientStates() { 1276 | const url = '/ibc/core/client/v1/client_states' 1277 | const res = await this.httpClient.send("get", url) 1278 | return res 1279 | } 1280 | 1281 | async queryClientStates(clientId) { 1282 | const url = '/ibc/core/client/v1/client_states/' + clientId 1283 | const res = await this.httpClient.send("get", url) 1284 | return res 1285 | } 1286 | 1287 | async queryClientConnections(clientId) { 1288 | const url = '/ibc/core/connection/v1/client_connections/' + clientId 1289 | const res = await this.httpClient.send("get", url) 1290 | return res 1291 | } 1292 | 1293 | async queryAllConnections() { 1294 | const url = '/ibc/core/connection/v1/connections' 1295 | const res = await this.httpClient.send("get", url) 1296 | return res 1297 | } 1298 | 1299 | async queryConnection(connectionId) { 1300 | const url = '/ibc/core/connection/v1/connections/' + connectionId 1301 | const res = await this.httpClient.send("get", url) 1302 | return res 1303 | } 1304 | 1305 | async queryAllChannels() { 1306 | const url = '/ibc/core/channel/v1/channels' 1307 | const res = await this.httpClient.send("get", url) 1308 | return res 1309 | } 1310 | 1311 | async queryChannel(channelId, portId) { 1312 | const url = '/ibc/core/channel/v1/channels/' + channelId + '/ports/' + portId 1313 | const res = await this.httpClient.send("get", url) 1314 | return res 1315 | } 1316 | 1317 | async queryPacketCommitments(channelId, portId, sequence) { 1318 | const url = '/ibc/core/channel/v1/channels/' + channelId + '/ports/' + portId + '/packet_commitments/' + sequence 1319 | const res = await this.httpClient.send("get", url) 1320 | return res 1321 | } 1322 | 1323 | async queryConnectionChannels(connectionId) { 1324 | const url = '/ibc/core/channel/v1/connections/' + connectionId + '/channels' 1325 | const res = await this.httpClient.send("get", url) 1326 | return res 1327 | } 1328 | 1329 | async queryTx(hash) { 1330 | const res = await this.httpClient.send("get", this.PostUrl + "/" + hash) 1331 | return res 1332 | } 1333 | 1334 | async queryTxs(event, page = 1, limit = 50, minHeight = 0, maxHeight = Number.MAX_SAFE_INTEGER) { 1335 | const url = this.PostUrl + '?message.action=' + event.action + '&message.sender=' + event.sender + '&page=' + page + '&limit=' + limit + '&tx.minheight=' + minHeight + '&tx.maxheight=' + maxHeight 1336 | const res = await this.httpClient.send("get", url) 1337 | return res 1338 | } 1339 | 1340 | async queryHeader(height = 1) { 1341 | const params = { 1342 | jsonrpc: "2.0", 1343 | id: 0, 1344 | method: "commit", 1345 | params: {height: height.toString()} 1346 | } 1347 | 1348 | const buf = JSON.stringify(params) 1349 | console.log(buf) 1350 | const opts = { 1351 | data: buf, 1352 | headers: { 1353 | "content-type": "text/plain", 1354 | } 1355 | } 1356 | const res = await this.rpcClient.send("post", null, null, opts) 1357 | 1358 | return res 1359 | } 1360 | 1361 | 1362 | } 1363 | -------------------------------------------------------------------------------- /src/crypto/fix-opts.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function (opts) { 3 | var out = { 4 | N: 16384, 5 | p: 1, 6 | r: 8, 7 | maxmem: 32 << 20 8 | }; 9 | if (!opts) { 10 | return out; 11 | } 12 | if (opts.N) { 13 | out.N = opts.N 14 | } else if (opts.cost) { 15 | out.N = opts.cost 16 | } 17 | if (opts.p) { 18 | out.p = opts.p 19 | } else if (opts.parallelization) { 20 | out.p = opts.parallelization 21 | } 22 | if (opts.r) { 23 | out.r = opts.r; 24 | } else if (opts.blockSize) { 25 | out.r = opts.blockSize 26 | } 27 | if (opts.maxmem) { 28 | out.maxmem = opts.maxmem 29 | } 30 | return out; 31 | } 32 | -------------------------------------------------------------------------------- /src/crypto/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module crypto 3 | */ 4 | 5 | import csprng from "secure-random" 6 | import bech32 from "bech32" 7 | import cryp from "crypto-browserify" 8 | import uuid from "uuid" 9 | import _ from "lodash" 10 | import bip39 from "bip39" 11 | import bip32 from "bip32" 12 | import { ec as EC } from "elliptic" 13 | import ecc from "tiny-secp256k1" 14 | import hexEncoding from "crypto-js/enc-hex" 15 | import SHA256 from "crypto-js/sha256" 16 | import RIPEMD160 from "crypto-js/ripemd160" 17 | import { Buffer } from "buffer" 18 | import secp256k1 from "secp256k1" 19 | import createKeccakHash from "keccak" 20 | import Hash from "eth-lib/lib/hash" 21 | import BN from 'bn.js' 22 | 23 | import { 24 | sha256ripemd160, 25 | } from "../utils" 26 | 27 | // 浏览器端实现 28 | const sync = require('./scrypt-sync') 29 | 30 | 31 | const MNEMONIC_ENTROPY_LEN = 128 32 | // const HD_PATH = "44'/996'/0'/0/0" 33 | 34 | /** 35 | * Get HD path by cointype param . 36 | * @param {string} cointype, default 60 37 | */ 38 | export const getHDPath = function (cointype) { 39 | return "44'/" + (cointype || '60') + "'/0'/0/0" 40 | } 41 | 42 | /** 43 | * Decode address from bech32 to buffer. 44 | * @param {string} addr bech32 format 45 | */ 46 | export const decodeAddressToBuffer = (addr) => { 47 | const decodedAddress = bech32.decode(addr) 48 | return Buffer.from(bech32.fromWords(decodedAddress.words)) 49 | } 50 | 51 | /** 52 | * Validate address. 53 | * @param {string} addr bech32 format 54 | * @return {boolean} 55 | */ 56 | export const validateAddress = (addr) => { 57 | try { 58 | const decodeAddress = bech32.decode(addr) 59 | if(decodeAddress.prefix === "ex") { 60 | return true 61 | } 62 | 63 | return false 64 | } catch(err) { 65 | return false 66 | } 67 | } 68 | 69 | /** 70 | * Encodes address from hex to bech32 format. 71 | * @param {string} hexAddr address in hex string 72 | * @param {string} prefix address prefix 73 | * @return {string} address with bech32 format 74 | */ 75 | export const encodeAddressToBech32 = (hexAddr, prefix = "ex") => { 76 | hexAddr = hexAddr.slice(0, 2) === '0x' ? hexAddr.slice(2) : hexAddr 77 | const words = bech32.toWords(Buffer.from(hexAddr, "hex")) 78 | return bech32.encode(prefix, words) 79 | } 80 | 81 | function buf2hex(buffer) { // buffer is an ArrayBuffer 82 | return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join(''); 83 | } 84 | 85 | /** 86 | * covert ex address to 0x address 87 | * @param bech32Address 88 | * @returns {Array} 89 | */ 90 | export const convertBech32ToHex = (bech32Address) => { 91 | const address = decodeAddressToBuffer(bech32Address) 92 | const hexAddress = toChecksumAddress("0x"+buf2hex(address)) 93 | return [hexAddress, encodeAddressToBech32(hexAddress.toLowerCase(), 'okexchain')] 94 | } 95 | /** 96 | * covert 0x address to ex address 97 | * @param hexAddress 98 | * @returns {Array} 99 | */ 100 | export const convertHexToBech32 = (hexAddress) => { 101 | return [encodeAddressToBech32(hexAddress.toLowerCase()), encodeAddressToBech32(hexAddress.toLowerCase(), 'okexchain')] 102 | } 103 | 104 | /** 105 | * covert okexchain address to ex address 106 | * @param bech32Address 107 | * @returns {String} 108 | */ 109 | export const convertOKExChainAddressToExAddress = (bech32Address) => { 110 | const address = decodeAddressToBuffer(bech32Address) 111 | const hexAddress = toChecksumAddress("0x"+buf2hex(address)) 112 | return encodeAddressToBech32(hexAddress.toLowerCase(), 'ex') 113 | } 114 | 115 | /** 116 | * Returns true if object is BN, otherwise false 117 | * 118 | * @method isBN 119 | * @param {Object} object 120 | * @return {Boolean} 121 | */ 122 | var isBN = function (object) { 123 | return BN.isBN(object); 124 | }; 125 | 126 | /** 127 | * Check if string is HEX, requires a 0x in front 128 | * 129 | * @method isHexStrict 130 | * @param {String} hex to be checked 131 | * @returns {Boolean} 132 | */ 133 | var isHexStrict = function (hex) { 134 | return ((_.isString(hex) || _.isNumber(hex)) && /^(-)?0x[0-9a-f]*$/i.test(hex)); 135 | }; 136 | 137 | /** 138 | * Hashes values to a sha3 hash using keccak 256 139 | * 140 | * To hash a HEX string the hex must have 0x in front. 141 | * 142 | * @method sha3 143 | * @return {String} the sha3 string 144 | */ 145 | var SHA3_NULL_S = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'; 146 | 147 | export const sha3 = function (value) { 148 | if (isBN(value)) { 149 | value = value.toString(); 150 | } 151 | 152 | if (isHexStrict(value) && /^0x/i.test((value).toString())) { 153 | value = hexToBytes(value); 154 | } 155 | 156 | var returnValue = Hash.keccak256(value); // jshint ignore:line 157 | 158 | if(returnValue === SHA3_NULL_S) { 159 | return null; 160 | } else { 161 | return returnValue; 162 | } 163 | }; 164 | 165 | /** 166 | * Converts to a checksum address 167 | * 168 | * @method toChecksumAddress 169 | * @param {String} address the given HEX address 170 | * @return {String} 171 | */ 172 | export const toChecksumAddress = function (address) { 173 | if (typeof address === 'undefined') return ''; 174 | 175 | if (!/^(0x)?[0-9a-f]{40}$/i.test(address)) 176 | throw new Error('Given address "'+ address +'" is not a valid Ethereum address.'); 177 | 178 | address = address.toLowerCase().replace(/^0x/i,''); 179 | var addressHash = sha3(address).replace(/^0x/i,''); 180 | var checksumAddress = '0x'; 181 | 182 | for (var i = 0; i < address.length; i++ ) { 183 | // If ith character is 8 to f then make it uppercase 184 | if (parseInt(addressHash[i], 16) > 7) { 185 | checksumAddress += address[i].toUpperCase(); 186 | } else { 187 | checksumAddress += address[i]; 188 | } 189 | } 190 | return checksumAddress; 191 | }; 192 | 193 | 194 | /** 195 | * Generates privateKey. 196 | * @param {number} len privateKey length (default: 32 bytes) 197 | * @return {string} privateKey hex string 198 | */ 199 | export const generatePrivateKey = (len = 32) => Buffer.from(csprng(len)).toString("hex") 200 | 201 | /** 202 | * Get publicKey from hex string. 203 | * @param {string} publicKey pubKey with hex string format 204 | * @return {Elliptic.PublicKey} pubKey 205 | */ 206 | export const getPubKeyFromHex = publicKey => { 207 | const cure = new EC("secp256k1") 208 | let keyPair = cure.keyFromPublic(publicKey, "hex") 209 | return keyPair.getPublic() 210 | } 211 | 212 | /** 213 | * Encode pubKey to compressed pubKey buffer. 214 | * @param {Elliptic.PublicKey} pubKey 215 | * @return {Buffer} 216 | */ 217 | export const encodePubKeyToCompressedBuffer = pubKey => { 218 | let prefix = 2 219 | if(pubKey.y.isOdd()){ 220 | prefix = 3 221 | } 222 | 223 | let pubBytes = Buffer.concat([ 224 | Buffer.alloc(1, prefix), 225 | pubKey.x.toArrayLike(Buffer, "be", 32) 226 | ]) 227 | return pubBytes 228 | } 229 | 230 | /** 231 | * Get public key from private key. 232 | * @param {string} privateKeyHex the private key hex string 233 | * @return {string} public key in hex string 234 | */ 235 | export const getPubKeyHexFromPrivateKey = privateKeyHex => { 236 | const curve = new EC("secp256k1") 237 | const keypair = curve.keyFromPrivate(privateKeyHex, "hex") 238 | const compressed = Buffer.from(keypair.getPublic().encodeCompressed()) 239 | return compressed.toString("hex") 240 | } 241 | /** 242 | * Get public key from private key. 243 | * @param {Buffer} privateKey 244 | * @return {Elliptic.PublicKey} PubKey 245 | * */ 246 | export const getPubKeyFromPrivateKey = privateKey => { 247 | const curve = new EC("secp256k1") 248 | const keypair = curve.keyFromPrivate(privateKey) 249 | return keypair.getPublic() 250 | } 251 | 252 | /** 253 | * Gets address from pubKey with hex format. 254 | * @param {string} publicKey publicKey hexstring 255 | * @param {string} prefix address prefix 256 | * @return {string} address 257 | */ 258 | export const getAddressFromPubKey = (publicKey, prefix) => { 259 | publicKey = publicKey.slice(0, 2) === '0x' ? publicKey.slice(2) : publicKey 260 | const publicKey1 = Buffer.from(publicKey, 'hex') 261 | publicKey = Buffer.from(secp256k1.publicKeyConvert(new Uint8Array(publicKey1), false)).slice(1) 262 | const hash = createKeccakHash('keccak256').update(publicKey).digest() 263 | return encodeAddressToBech32(hash.slice(-20).toString('hex'), prefix) 264 | } 265 | 266 | export const getAddressFromPublicKeyLegacy = (publicKeyHex, prefix) => { 267 | // const pubKey = ec.keyFromPublic(publicKeyHex, "hex") 268 | // const pubPoint = pubKey.getPublic() 269 | // const compressed = pubPoint.encodeCompressed() 270 | // const hexed = ab2hexstring(compressed) 271 | const hash = sha256ripemd160(publicKeyHex) // https://git.io/fAn8N 272 | const address = encodeAddress(hash, prefix) 273 | return address 274 | } 275 | 276 | export const encodeAddress = (value, prefix = "ex", type = "hex") => { 277 | const words = bech32.toWords(Buffer.from(value, type)) 278 | return bech32.encode(prefix, words) 279 | } 280 | 281 | /** 282 | * Get address from private key. 283 | * @param {string} privateKeyHex the private key hexstring 284 | * @param {string} prefix address prefix 285 | * @return {string} address 286 | */ 287 | export const getAddressFromPrivateKey = (privateKeyHex, prefix) => { 288 | return getAddressFromPubKey(getPubKeyHexFromPrivateKey(privateKeyHex), prefix) 289 | } 290 | 291 | export const getAddressFromPrivateKeyLegacy = (privateKeyHex, prefix) => { 292 | return getAddressFromPublicKeyLegacy(getPubKeyHexFromPrivateKey(privateKeyHex), prefix) 293 | } 294 | 295 | /** 296 | * Sign msg with privateKey and Msg in hex format. 297 | * @param {string} msgHex msg in hex format. 298 | * @param {string} privateKey - The private key in hex format. 299 | * @return {Buffer} Signature. 300 | */ 301 | export const sign = (msgHex, privateKey) => { 302 | const msg = Buffer.from(msgHex, "hex") 303 | const msgHash = createKeccakHash('keccak256').update(msg).digest() 304 | const signature = ecc.sign(msgHash, Buffer.from(privateKey, "hex")) // enc ignored if buffer 305 | return signature 306 | } 307 | 308 | /** 309 | * Generates a signature (64 byte ) for a transaction based on given private key. 310 | * @param {string} signBytesHex - Unsigned transaction sign bytes hexstring. 311 | * @param {string | Buffer} privateKey - The private key. 312 | * @return {Buffer} Signature. Does not include tx. 313 | */ 314 | export const signPrivateKeyOldAddress = (signBytesHex, privateKey) => { 315 | const msgHash = sha256(signBytesHex) 316 | const msgHashHex = Buffer.from(msgHash, "hex") 317 | const signature = ecc.sign(msgHashHex, Buffer.from(privateKey, "hex")) // enc ignored if buffer 318 | return signature 319 | } 320 | 321 | /** 322 | * Validate signature. 323 | * @param {string} sigHex signature in hex format 324 | * @param {string} msgHex msg in hex format. 325 | * @param {string} pubKeyHex public key in hex format 326 | * @return {boolean} 327 | */ 328 | export const validateSig = (sigHex, msgHex, pubKeyHex) => { 329 | const publicKey = Buffer.from(pubKeyHex, "hex") 330 | if (!ecc.isPoint(publicKey)) throw new Error("invalid pubKey") 331 | const msg = Buffer.from(msgHex, "hex") 332 | const msgHashHex = createKeccakHash('keccak256').update(msg).digest() 333 | const msgHash = Buffer.from(msgHashHex, "hex") 334 | return ecc.verify(msgHash, publicKey, Buffer.from(sigHex, "hex")) 335 | } 336 | 337 | /** 338 | * Generate KeyStore with privateKey and password. 339 | * @param {string} privateKeyHex 340 | * @param {string} password 341 | * @returns {object} 342 | */ 343 | export const generateKeyStore = (privateKeyHex, password) => { 344 | const salt = cryp.randomBytes(32) 345 | const iv = cryp.randomBytes(16) 346 | const cipherAlg = "aes-128-ctr" 347 | 348 | const kdf = "scrypt" 349 | const kdfparams = { 350 | dklen: 32, 351 | salt: salt.toString("hex"), 352 | n: 262144, 353 | p: 1, 354 | r: 8, 355 | //prf: "hmac-sha256" 356 | } 357 | const options = { 358 | N: kdfparams.n, 359 | r: kdfparams.r, 360 | p: kdfparams.p, 361 | maxmem: 1024*1024*1024*2, 362 | } 363 | 364 | const derivedKey = sync(Buffer.from(password),salt,kdfparams.dklen,options) 365 | const cipher = cryp.createCipheriv(cipherAlg, derivedKey.slice(0, 16), iv) 366 | if (!cipher) { 367 | throw new Error("createCipheriv has been failed") 368 | } 369 | 370 | const ciphertext = Buffer.concat([cipher.update(Buffer.from(privateKeyHex.toLowerCase(), "hex")), cipher.final()]) 371 | const bufferValue = Buffer.concat([derivedKey.slice(16, 32), Buffer.from(ciphertext, "hex")]) 372 | return { 373 | crypto: { 374 | ciphertext: ciphertext.toString("hex"), 375 | cipherparams: { 376 | iv: iv.toString("hex") 377 | }, 378 | cipher: cipherAlg, 379 | kdf, 380 | kdfparams: kdfparams, 381 | mac: sha256(bufferValue.toString("hex")) 382 | }, 383 | id: uuid.v4({ 384 | random: cryp.randomBytes(16) 385 | }), 386 | version: 3, 387 | } 388 | } 389 | /** 390 | * Get privateKey from keyStore. 391 | * @param {string | object} keystore 392 | * @param {string} password 393 | * @returns {string} privateKey 394 | */ 395 | export const getPrivateKeyFromKeyStore = (keystore, password) => { 396 | 397 | if (!_.isString(password)) { 398 | throw new Error("invalid password") 399 | } 400 | 401 | const json = _.isObject(keystore) ? keystore : JSON.parse(keystore) 402 | const kdfparams = json.crypto.kdfparams 403 | const options = { 404 | N: kdfparams.n, 405 | r: kdfparams.r, 406 | p: kdfparams.p, 407 | maxmem: 1024*1024*1024*2, 408 | } 409 | const derivedKey = sync(Buffer.from(password),Buffer.from(kdfparams.salt, "hex"),kdfparams.dklen,options) 410 | const ciphertext = Buffer.from(json.crypto.ciphertext, "hex") 411 | const bufferValue = Buffer.concat([derivedKey.slice(16, 32), ciphertext]) 412 | const mac = sha256(bufferValue.toString("hex")) 413 | 414 | if (mac !== json.crypto.mac) { 415 | throw new Error("invalid password") 416 | } 417 | const decipher = cryp.createDecipheriv(json.crypto.cipher, derivedKey.slice(0, 16), Buffer.from(json.crypto.cipherparams.iv, "hex")) 418 | const privateKey = Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("hex") 419 | 420 | return privateKey 421 | } 422 | 423 | /** 424 | * Generate mnemonic. 425 | * @return {string} 426 | */ 427 | export const generateMnemonic = () => bip39.generateMnemonic(MNEMONIC_ENTROPY_LEN) 428 | 429 | /** 430 | * Validate mnemonic. 431 | * @param {string} mnemonic. 432 | * @return {bool} 433 | */ 434 | export const validateMnemonic = bip39.validateMnemonic 435 | 436 | /** 437 | * Get private key from mnemonic. 438 | * @param {string} mnemonic 439 | * @param {string} cointype, default 60 440 | * @return {string} hexstring 441 | */ 442 | export const getPrivateKeyFromMnemonic = (mnemonic, cointype) => { 443 | if(!bip39.validateMnemonic(mnemonic)){ 444 | throw new Error("invalid mnemonic format") 445 | } 446 | const seed = bip39.mnemonicToSeed(mnemonic) 447 | const master = bip32.fromSeed(seed) 448 | const child = master.derivePath(getHDPath(cointype)) 449 | return child.privateKey.toString("hex") 450 | } 451 | 452 | 453 | /** 454 | * Just like ripemd160(sha256(hex)) 455 | * @param {string} hex 456 | * @returns {string} hash 457 | */ 458 | export const sha256Ripemd160 = (hex) => { 459 | if (typeof hex !== "string") throw new Error("invalid param, need hex string") 460 | if (hex.length % 2 !== 0) throw new Error(`invalid hex string length: ${hex}`) 461 | const hexEncoded = hexEncoding.parse(hex) 462 | const ProgramSha256 = SHA256(hexEncoded) 463 | return RIPEMD160(ProgramSha256).toString() 464 | } 465 | 466 | /** 467 | * SHA256. 468 | * @param {string} hex 469 | * @returns {string} hash 470 | */ 471 | export const sha256 = (hex) => { 472 | if (typeof hex !== "string") throw new Error("invalid param,need hex string") 473 | if (hex.length % 2 !== 0) throw new Error(`invalid hex string length: ${hex}`) 474 | const hexEncoded = hexEncoding.parse(hex) 475 | return SHA256(hexEncoded).toString() 476 | } 477 | 478 | -------------------------------------------------------------------------------- /src/crypto/scrypt-rom.js: -------------------------------------------------------------------------------- 1 | 2 | function blockxor(S, Si, D, Di, len){ 3 | var i = -1; 4 | while (++i < len) { 5 | D[Di + i] ^= S[Si + i] 6 | } 7 | } 8 | function arraycopy (src, srcPos, dest, destPos, length) { 9 | src.copy(dest, destPos, srcPos, srcPos + length) 10 | } 11 | 12 | var Buffer = require('safe-buffer').Buffer 13 | 14 | module.exports = ScryptRom 15 | 16 | function ScryptRom (b, r, N, p) { 17 | this.B = b 18 | this.r = r 19 | this.N = N 20 | this.p = p 21 | this.XY = Buffer.allocUnsafe(256 * r) 22 | this.V = Buffer.allocUnsafe(128 * r * N) 23 | this.B32 = new Int32Array(16) // salsa20_8 24 | this.x = new Int32Array(16) // salsa20_8 25 | this._X = Buffer.allocUnsafe(64) // blockmix_salsa8 26 | } 27 | ScryptRom.prototype.run = function () { 28 | var p = this.p | 0 29 | var r = this.r | 0 30 | for (var i = 0;i < p;i++) { 31 | this.scryptROMix(i, r) 32 | } 33 | return this.B 34 | } 35 | ScryptRom.prototype.scryptROMix = function (i, r) { 36 | var blockStart = i * 128 * r 37 | var offset = (2 * r - 1) * 64 38 | var blockLen = 128 * r 39 | var B = this.B 40 | var N = this.N | 0 41 | var V = this.V 42 | var XY = this.XY 43 | B.copy(XY, 0, blockStart, blockStart + blockLen) 44 | for (var i1 = 0; i1 < N; i1++) { 45 | XY.copy(V, i1 * blockLen, 0, blockLen) 46 | this.blockmix_salsa8(blockLen) 47 | } 48 | 49 | var j; 50 | for (var i2 = 0;i2 < N;i2++) { 51 | j = XY.readUInt32LE(offset) & (N - 1) 52 | blockxor(V, j * blockLen, XY, 0, blockLen) 53 | this.blockmix_salsa8(blockLen) 54 | } 55 | XY.copy(B, blockStart, 0, blockLen) 56 | } 57 | ScryptRom.prototype.blockmix_salsa8 = function (blockLen) { 58 | var BY = this.XY 59 | var r = this.r 60 | var _X = this._X 61 | arraycopy(BY, (2 * r - 1) * 64, _X, 0, 64) 62 | var i 63 | for (i = 0;i < 2 * r;i++) { 64 | blockxor(BY, i * 64, _X, 0, 64) 65 | this.salsa20_8() 66 | arraycopy(_X, 0, BY, blockLen + (i * 64), 64) 67 | } 68 | for (i = 0;i < r;i++) { 69 | arraycopy(BY, blockLen + (i * 2) * 64, BY, (i * 64), 64) 70 | arraycopy(BY, blockLen + (i * 2 + 1) * 64, BY, (i + r) * 64, 64) 71 | } 72 | } 73 | ScryptRom.prototype.salsa20_8 = function () { 74 | var B32 = this.B32 75 | var B = this._X 76 | var x = this.x 77 | 78 | var i 79 | for (i = 0;i < 16;i++) { 80 | B32[i] = (B[i * 4 + 0] & 0xff) << 0 81 | B32[i] |= (B[i * 4 + 1] & 0xff) << 8 82 | B32[i] |= (B[i * 4 + 2] & 0xff) << 16 83 | B32[i] |= (B[i * 4 + 3] & 0xff) << 24 84 | } 85 | 86 | for (i = 0;i < 16;i++) { 87 | x[i] = B32[i] 88 | } 89 | 90 | for (i = 0;i < 4;i++) { 91 | x[4] ^= R(x[0] + x[12], 7) 92 | x[8] ^= R(x[4] + x[0], 9) 93 | x[12] ^= R(x[8] + x[4], 13) 94 | x[0] ^= R(x[12] + x[8], 18) 95 | x[9] ^= R(x[5] + x[1], 7) 96 | x[13] ^= R(x[9] + x[5], 9) 97 | x[1] ^= R(x[13] + x[9], 13) 98 | x[5] ^= R(x[1] + x[13], 18) 99 | x[14] ^= R(x[10] + x[6], 7) 100 | x[2] ^= R(x[14] + x[10], 9) 101 | x[6] ^= R(x[2] + x[14], 13) 102 | x[10] ^= R(x[6] + x[2], 18) 103 | x[3] ^= R(x[15] + x[11], 7) 104 | x[7] ^= R(x[3] + x[15], 9) 105 | x[11] ^= R(x[7] + x[3], 13) 106 | x[15] ^= R(x[11] + x[7], 18) 107 | x[1] ^= R(x[0] + x[3], 7) 108 | x[2] ^= R(x[1] + x[0], 9) 109 | x[3] ^= R(x[2] + x[1], 13) 110 | x[0] ^= R(x[3] + x[2], 18) 111 | x[6] ^= R(x[5] + x[4], 7) 112 | x[7] ^= R(x[6] + x[5], 9) 113 | x[4] ^= R(x[7] + x[6], 13) 114 | x[5] ^= R(x[4] + x[7], 18) 115 | x[11] ^= R(x[10] + x[9], 7) 116 | x[8] ^= R(x[11] + x[10], 9) 117 | x[9] ^= R(x[8] + x[11], 13) 118 | x[10] ^= R(x[9] + x[8], 18) 119 | x[12] ^= R(x[15] + x[14], 7) 120 | x[13] ^= R(x[12] + x[15], 9) 121 | x[14] ^= R(x[13] + x[12], 13) 122 | x[15] ^= R(x[14] + x[13], 18) 123 | } 124 | for (i = 0;i < 16;i++) { 125 | B32[i] += x[i] 126 | } 127 | var bi 128 | 129 | for (i = 0;i < 16;i++) { 130 | bi = i * 4 131 | B[bi + 0] = (B32[i] >> 0 & 0xff) 132 | B[bi + 1] = (B32[i] >> 8 & 0xff) 133 | B[bi + 2] = (B32[i] >> 16 & 0xff) 134 | B[bi + 3] = (B32[i] >> 24 & 0xff) 135 | } 136 | } 137 | ScryptRom.prototype.clean = function () { 138 | this.XY.fill(0) 139 | this.V.fill(0) 140 | this._X.fill(0) 141 | this.B.fill(0) 142 | for (var i = 0;i < 16;i++) { 143 | this.B32[i] = 0 144 | this.x[i] = 0 145 | } 146 | } 147 | function R (a, b) { 148 | return (a << b) | (a >>> (32 - b)) 149 | } 150 | -------------------------------------------------------------------------------- /src/crypto/scrypt-sync.js: -------------------------------------------------------------------------------- 1 | // var pbkdf2 = require('pbkdf2').pbkdf2Sync 2 | const crypto = require('crypto') 3 | // import crypto from 'crypto'; 4 | var fixOpts = require('./fix-opts') 5 | var ScryptRom = require('./scrypt-rom'); 6 | module.exports = scryptSync 7 | function scryptSync(password, salt, keylen, _opts) { 8 | var opts = fixOpts(_opts); 9 | var N = opts.N 10 | var r = opts.r 11 | var p = opts.p 12 | var maxmem = opts.maxmem 13 | var blen = p * 128 * r 14 | var vlen = 32 * r * (N + 2) * 4 15 | if (vlen + blen > maxmem) { 16 | throw new Error('excedes max memory') 17 | } 18 | var b = crypto.pbkdf2Sync(password, salt, 1, blen, 'sha256') 19 | 20 | var scryptRom = new ScryptRom(b, r, N, p) 21 | var out = scryptRom.run(); 22 | 23 | var fin = crypto.pbkdf2Sync(password, out, 1, keylen, 'sha256') 24 | scryptRom.clean() 25 | return fin 26 | } 27 | -------------------------------------------------------------------------------- /src/httpProxy.js: -------------------------------------------------------------------------------- 1 | import axios from "axios" 2 | import {obj} from "pumpify"; 3 | /** 4 | * HttpProxy 5 | */ 6 | class HttpProxy { 7 | constructor(baseURL){ 8 | axios.defaults.timeout = 300000 9 | this.httpClient = axios.create({ baseURL }) // withCredentials: true 10 | } 11 | 12 | send(method, path, params, opts) { 13 | const paramsObj = { method, url: path, ...opts } 14 | console.log(paramsObj) 15 | if (params) { 16 | method === "get" ? paramsObj.params = params : paramsObj.data = params 17 | } 18 | 19 | const cosmosCode = { 20 | "1": 60001, 21 | "2": 60002, 22 | "3": 60003, 23 | "4": 60004, 24 | "5": 60005, 25 | "6": 60006, 26 | "7": 60007, 27 | "8": 60008, 28 | "9": 60009, 29 | "10": 60010, 30 | "11": 60011, 31 | "12": 60012, 32 | "13": 60013, 33 | "14": 60014, 34 | "15": 60015, 35 | "16": 60016, 36 | "17": 60017, 37 | "18": 60018, 38 | "19": 60019, 39 | "20": 60020, 40 | "21": 60021, 41 | "111222": 60099 42 | } 43 | 44 | return this.httpClient 45 | .request(paramsObj) 46 | .then(response => { 47 | 48 | if (method === 'get') { 49 | return { result: response.data, status: response.status } 50 | } 51 | let fmtResponse = { 52 | code: 0, 53 | data: '', 54 | msg: 'success', 55 | detail_msg: '' 56 | } 57 | const data = response.data || null 58 | if(data) { 59 | if (data.code) { 60 | fmtResponse.code = cosmosCode[data.code] ? cosmosCode[data.code] : data.code 61 | fmtResponse.msg = data.raw_log || '' 62 | fmtResponse.detail_msg = fmtResponse.msg 63 | } else { 64 | fmtResponse.data = data.txhash || '' 65 | } 66 | } else { 67 | fmtResponse.code = -1 68 | fmtResponse.data = '' 69 | fmtResponse.msg = 'response data return null' 70 | } 71 | return { result: fmtResponse, status: response.status } 72 | }).catch(err => { 73 | let fmtResponse = { 74 | code: -1, 75 | data: '', 76 | msg: err.response && err.response.data, 77 | detail_msg: '' 78 | } 79 | try { 80 | fmtResponse.msg = JSON.stringify(fmtResponse.msg) 81 | } catch (e) { 82 | fmtResponse.msg = err.response && err.response.data 83 | } 84 | console.error("HttpProxy", err.response && err.response.data) 85 | const cmErr = err.response.data 86 | if (cmErr && cmErr.code && cmErr.code > 0) { 87 | fmtResponse.code = cosmosCode[cmErr.code] ? cosmosCode[cmErr.code] : -1 88 | fmtResponse.msg = cmErr.raw_log || '' 89 | return { result: fmtResponse, status: 200 } 90 | } 91 | return { result: fmtResponse, status: 200 } 92 | }) 93 | } 94 | } 95 | 96 | export default HttpProxy 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import "babel-polyfill" 2 | import * as client from "./client" 3 | import * as crypto from "./crypto" 4 | import * as wallet from "./wallet" 5 | import {OKCSecp256k1Wallet} from "./secp256k1/secp256k1wallet"; 6 | 7 | const { OKEXChainClient } = client 8 | module.exports = OKEXChainClient 9 | module.exports.crypto = crypto; 10 | module.exports.wallet = wallet; 11 | module.exports.OKCSecp256k1Wallet = OKCSecp256k1Wallet 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/rpcProxy.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | class RpcProxy { 4 | constructor(baseURL){ 5 | this.httpClient = axios.create({ baseURL }) // withCredentials: true 6 | } 7 | 8 | send(method, path, params, opts) { 9 | const paramsObj = { method, url: path, ...opts } 10 | console.log(paramsObj) 11 | if (params) { 12 | method === "get" ? paramsObj.params = params : paramsObj.data = params 13 | } 14 | return this.httpClient 15 | .request(paramsObj) 16 | .then(response => { 17 | 18 | if (method === 'get') { 19 | return { result: response.data, status: response.status } 20 | } 21 | return response.data 22 | }).catch(err => { 23 | let fmtResponse = { 24 | jsonrpc: "2.0", 25 | id: '0', 26 | err: { 27 | code: -1, 28 | message: err.response, 29 | data: '' 30 | } 31 | } 32 | console.log(err) 33 | return fmtResponse 34 | }) 35 | } 36 | } 37 | 38 | export default RpcProxy -------------------------------------------------------------------------------- /src/secp256k1/secp256k1wallet.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | import secp256k1 from "secp256k1"; 3 | 4 | Object.defineProperty(exports, "__esModule", {value: true}); 5 | exports.OKCSecp256k1Wallet = void 0; 6 | const crypto_1 = require("@cosmjs/crypto"); 7 | const signature_1 = require("@cosmjs/amino"); 8 | const signdoc_1 = require("@cosmjs/amino"); 9 | import * as crypto from "../crypto"; 10 | 11 | import {Buffer} from "buffer"; 12 | import * as web3 from "web3" 13 | 14 | 15 | /** 16 | * A wallet that holds a single secp256k1 keypair. 17 | * 18 | * If you want to work with BIP39 mnemonics and multiple accounts, use Secp256k1HdWallet. 19 | */ 20 | class OKCSecp256k1Wallet { 21 | constructor(privkey, pubkey, prefix) { 22 | this.privkey = privkey; 23 | this.pubkey = pubkey; 24 | this.prefix = prefix; 25 | } 26 | 27 | /** 28 | * Creates a Secp256k1Wallet from the given private key 29 | * 30 | * @param privkey The private key. 31 | * @param prefix The bech32 address prefix (human readable part). Defaults to "ex". 32 | */ 33 | static async fromKey(privkey, prefix = "ex") { 34 | const pk = crypto.encodePubKeyToCompressedBuffer(crypto.getPubKeyFromPrivateKey(privkey)) 35 | return new OKCSecp256k1Wallet(privkey, Uint8Array.from(pk), prefix) 36 | } 37 | 38 | get address() { 39 | const bech32 = crypto.getAddressFromPrivateKey(Buffer.from(this.privkey).toString('hex')) 40 | return crypto.convertBech32ToHex(bech32)[0] 41 | } 42 | 43 | async getAccounts() { 44 | return [{ 45 | algo: "secp256k1", address: this.address, pubkey: this.pubkey, 46 | },]; 47 | } 48 | 49 | async signAmino(signerAddress, signDoc) { 50 | if (signerAddress !== this.address) { 51 | throw new Error(`Address ${signerAddress} not found in wallet`); 52 | } 53 | const message = web3.default.utils.sha3(Buffer.from((0, signdoc_1.serializeSignDoc)(signDoc))) 54 | const signature = await crypto_1.Secp256k1.createSignature(Uint8Array.from(Buffer.from(message.substring(2), 'hex')), this.privkey); 55 | const signatureBytes = new Uint8Array([...signature.r(32), ...signature.s(32)]); 56 | return { 57 | signed: signDoc, signature: (0, signature_1.encodeSecp256k1Signature)(this.pubkey, signatureBytes), 58 | } 59 | } 60 | } 61 | 62 | exports.OKCSecp256k1Wallet = OKCSecp256k1Wallet; 63 | -------------------------------------------------------------------------------- /src/transaction.js: -------------------------------------------------------------------------------- 1 | import * as crypto from "./crypto/" 2 | import * as wallet from "./wallet" 3 | 4 | /** 5 | * Transaction 6 | * @param {String} param.account_number 7 | * @param {String} param.chain_id 8 | * @param {Object} param.fee 9 | * @param {String} param.memo 10 | * @param {Object} param.msg 11 | * @param {String} param.sequence 12 | */ 13 | class Transaction { 14 | constructor(param) { 15 | this.account_number = param.account_number 16 | this.chain_id = param.chain_id 17 | this.fee = param.fee 18 | this.msgs = param.msg 19 | this.memo = param.memo 20 | this.sequence = param.sequence 21 | } 22 | 23 | 24 | /** 25 | * @param {String | Object} privateKeyHexOrSigner 26 | * @param {Object} msg 27 | * @param {String} address 28 | * @return {Transaction} 29 | **/ 30 | async sign(privateKeyHexOrSigner, msg, address, isPrivatekeyOldAddress) { 31 | 32 | const signMsg = { 33 | "account_number": this.account_number.toString(), 34 | "chain_id": this.chain_id, 35 | "fee": this.fee, 36 | "memo": this.memo, 37 | "msgs": msg, 38 | "sequence": this.sequence.toString(), 39 | } 40 | 41 | console.log(signMsg) 42 | 43 | let signatures; 44 | 45 | // PrivatekeyHex 46 | if (typeof privateKeyHexOrSigner === 'string') { 47 | const jsonStr = JSON.stringify(signMsg) 48 | const signBytes = Buffer.from(jsonStr) 49 | const privateKey = Buffer.from(privateKeyHexOrSigner, "hex") 50 | const signature = isPrivatekeyOldAddress ? crypto.signPrivateKeyOldAddress(signBytes.toString("hex"), privateKey) 51 | : crypto.sign(signBytes.toString("hex"), privateKey) 52 | const pubKey = crypto.encodePubKeyToCompressedBuffer(crypto.getPubKeyFromPrivateKey(privateKey)) 53 | signatures = [{ 54 | pub_key: { 55 | type: isPrivatekeyOldAddress ? "tendermint/PubKeySecp256k1" : "ethermint/PubKeyEthSecp256k1", 56 | value:pubKey}, 57 | signature: signature, 58 | }] 59 | } 60 | // External Signer 61 | if (typeof privateKeyHexOrSigner === 'object') { 62 | let result = await privateKeyHexOrSigner.sign(signMsg, address); 63 | signatures = result.signatures; 64 | } 65 | 66 | this.signatures = signatures; 67 | 68 | return this 69 | } 70 | 71 | /** 72 | * @param {Object} msg 73 | * @return {Transaction} 74 | **/ 75 | async signByWallet(msg) { 76 | 77 | const signMsg = { 78 | to: '', 79 | symbol: 'OKT', 80 | memo: this.memo, 81 | // contractAddress:'', 82 | decimalNum: '0', 83 | accountNumber:this.account_number.toString(), 84 | sequenceNumber:this.sequence.toString(), 85 | value: '0', 86 | gasLimit: this.fee.gas, 87 | gasPrice: this.fee.amount[0].amount, 88 | data: JSON.stringify(msg) 89 | } 90 | 91 | console.log("signmsg: ",JSON.stringify(signMsg)) 92 | 93 | this.signatures = await wallet.sign(signMsg); 94 | 95 | return this 96 | } 97 | 98 | /** 99 | * @param {string} mode 100 | * @return {Object} 101 | */ 102 | serializeTransactionWithJson(mode){ 103 | if(!this.signatures) { 104 | throw new Error("null signature") 105 | } 106 | 107 | const stdTx = { 108 | msg: this.msgs, 109 | fee: this.fee, 110 | signatures: this.signatures, 111 | memo: this.memo, 112 | } 113 | stdTx.signatures = stdTx.signatures.map((item) => { 114 | item.pub_key.value=item.pub_key.value.toString("base64") 115 | item.signature=item.signature.toString("base64") 116 | return item 117 | }) 118 | return JSON.stringify({ 119 | mode: mode, 120 | type: "cosmos-sdk/StdTx", 121 | tx: stdTx, 122 | nonce: this.sequence.toString(), 123 | }) 124 | } 125 | 126 | 127 | } 128 | 129 | 130 | export default Transaction 131 | -------------------------------------------------------------------------------- /src/utils/encoderHelper.js: -------------------------------------------------------------------------------- 1 | import _ from "lodash" 2 | 3 | // typeToTyp3 4 | //amino type convert 5 | export default type => { 6 | if(_.isBoolean(type)){ 7 | return 0 8 | } 9 | 10 | if(_.isNumber(type)){ 11 | if(_.isInteger(type)){ 12 | return 0 13 | }else{ 14 | return 1 15 | } 16 | } 17 | 18 | if(_.isString(type) || _.isArray(type) || _.isObject(type)){ 19 | return 2 20 | } 21 | } 22 | 23 | export const size = function (items, iter, acc) { 24 | if (acc === undefined) acc = 0 25 | for (var i = 0; i < items.length; ++i) acc += iter(items[i], i, acc) 26 | return acc 27 | } 28 | 29 | export const isAbstractCodec = function (codec) { 30 | return (codec && 31 | typeof codec.encode === "function" && 32 | typeof codec.decode === "function" && 33 | typeof codec.encodingLength === "function") 34 | } 35 | -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module utils 3 | */ 4 | 5 | import hexEncoding from "crypto-js/enc-hex" 6 | import SHA256 from "crypto-js/sha256" 7 | import RIPEMD160 from "crypto-js/ripemd160" 8 | 9 | /** 10 | * @param {arrayBuffer} buf 11 | * @returns {string} ASCII string 12 | */ 13 | export const ab2str = buf => 14 | String.fromCharCode.apply(null, new Uint8Array(buf)) 15 | 16 | /** 17 | * @param {string} str - ASCII string 18 | * @returns {arrayBuffer} 19 | */ 20 | export const str2ab = str => { 21 | if (typeof str !== "string") { 22 | throw new Error("str2ab expects a string") 23 | } 24 | const result = new Uint8Array(str.length) 25 | for (let i = 0, strLen = str.length; i < strLen; i++) { 26 | result[i] = str.charCodeAt(i) 27 | } 28 | return result 29 | } 30 | 31 | /** 32 | * @param {string} str - HEX string 33 | * @returns {number[]} 34 | */ 35 | export const hexstring2ab = str => { 36 | ensureHex(str) 37 | if (!str.length) return new Uint8Array() 38 | const iters = str.length / 2 39 | const result = new Uint8Array(iters) 40 | for (let i = 0; i < iters; i++) { 41 | result[i] = parseInt(str.substring(0, 2), 16) 42 | str = str.substring(2) 43 | } 44 | return result 45 | } 46 | 47 | /** 48 | * @param {arrayBuffer} arr 49 | * @returns {string} HEX string 50 | */ 51 | export const ab2hexstring = arr => { 52 | if (typeof arr !== "object") { 53 | throw new Error("ab2hexstring expects an array") 54 | } 55 | let result = "" 56 | for (let i = 0; i < arr.length; i++) { 57 | let str = arr[i].toString(16) 58 | str = str.length === 0 ? "00" 59 | : str.length === 1 ? "0" + str 60 | : str 61 | result += str 62 | } 63 | return result 64 | } 65 | 66 | /** 67 | * @param {string} str - ASCII string 68 | * @returns {string} HEX string 69 | */ 70 | export const str2hexstring = str => ab2hexstring(str2ab(str)) 71 | 72 | /** 73 | * @param {string} hexstring - HEX string 74 | * @returns {string} ASCII string 75 | */ 76 | export const hexstring2str = hexstring => ab2str(hexstring2ab(hexstring)) 77 | 78 | /** 79 | * convert an integer to big endian hex and add leading zeros 80 | * @param {Number} num 81 | * @returns {string} 82 | */ 83 | export const int2hex = num => { 84 | if (typeof num !== "number") { 85 | throw new Error("int2hex expects a number") 86 | } 87 | let h = num.toString(16) 88 | return h.length % 2 ? "0" + h : h 89 | } 90 | 91 | /** 92 | * Converts a number to a big endian hexstring of a suitable size, optionally little endian 93 | * @param {Number} num 94 | * @param {Number} size - The required size in bytes, eg 1 for Uint8, 2 for Uint16. Defaults to 1. 95 | * @param {Boolean} littleEndian - Encode the hex in little endian form 96 | * @return {string} 97 | */ 98 | export const num2hexstring = (num, size = 1, littleEndian = false) => { 99 | if (typeof num !== "number") throw new Error("num must be numeric") 100 | if (num < 0) throw new RangeError("num is unsigned (>= 0)") 101 | if (size % 1 !== 0) throw new Error("size must be a whole integer") 102 | if (!Number.isSafeInteger(num)) throw new RangeError(`num (${num}) must be a safe integer`) 103 | size = size * 2 104 | let hexstring = num.toString(16) 105 | hexstring = hexstring.length % size === 0 ? hexstring : ("0".repeat(size) + hexstring).substring(hexstring.length) 106 | if (littleEndian) hexstring = reverseHex(hexstring) 107 | return hexstring 108 | } 109 | 110 | /** 111 | * Converts a number to a variable length Int. Used for array length header 112 | * @param {Number} num - The number 113 | * @returns {string} hexstring of the variable Int. 114 | */ 115 | export const num2VarInt = (num) => { 116 | if (num < 0xfd) { 117 | return num2hexstring(num) 118 | } else if (num <= 0xffff) { 119 | // uint16 120 | return "fd" + num2hexstring(num, 2, true) 121 | } else if (num <= 0xffffffff) { 122 | // uint32 123 | return "fe" + num2hexstring(num, 4, true) 124 | } else { 125 | // uint64 126 | return "ff" + num2hexstring(num, 8, true) 127 | } 128 | } 129 | 130 | /** 131 | * XORs two hexstrings 132 | * @param {string} str1 - HEX string 133 | * @param {string} str2 - HEX string 134 | * @returns {string} XOR output as a HEX string 135 | */ 136 | export const hexXor = (str1, str2) => { 137 | ensureHex(str1) 138 | ensureHex(str2) 139 | if (str1.length !== str2.length) throw new Error("strings are disparate lengths") 140 | const result = [] 141 | for (let i = 0; i < str1.length; i += 2) { 142 | result.push(parseInt(str1.substr(i, 2), 16) ^ parseInt(str2.substr(i, 2), 16)) 143 | } 144 | return ab2hexstring(result) 145 | } 146 | 147 | /** 148 | * Reverses an array. Accepts arrayBuffer. 149 | * @param {Array} arr 150 | * @returns {Uint8Array} 151 | */ 152 | export const reverseArray = arr => { 153 | if (typeof arr !== "object" || !arr.length) throw new Error("reverseArray expects an array") 154 | let result = new Uint8Array(arr.length) 155 | for (let i = 0; i < arr.length; i++) { 156 | result[i] = arr[arr.length - 1 - i] 157 | } 158 | 159 | return result 160 | } 161 | 162 | /** 163 | * Reverses a HEX string, treating 2 chars as a byte. 164 | * @example 165 | * reverseHex('abcdef') = 'efcdab' 166 | * @param {string} hex - HEX string 167 | * @return {string} HEX string reversed in 2s. 168 | */ 169 | export const reverseHex = hex => { 170 | ensureHex(hex) 171 | let out = "" 172 | for (let i = hex.length - 2; i >= 0; i -= 2) { 173 | out += hex.substr(i, 2) 174 | } 175 | return out 176 | } 177 | 178 | const hexRegex = /^([0-9A-Fa-f]{2})*$/ 179 | 180 | /** 181 | * Checks if input is a hexstring. Empty string is considered a hexstring. 182 | * @example 183 | * isHex('0101') = true 184 | * isHex('') = true 185 | * isHex('0x01') = false 186 | * @param {string} str 187 | * @return {boolean} 188 | */ 189 | export const isHex = str => { 190 | try { 191 | return hexRegex.test(str) 192 | } catch (err) { return false } 193 | } 194 | 195 | /** 196 | * Throws an error if input is not hexstring. 197 | * @param {string} str 198 | */ 199 | export const ensureHex = str => { 200 | if (!isHex(str)) throw new Error(`Expected a hexstring but got ${str}`) 201 | } 202 | 203 | /** 204 | * Performs a SHA256 followed by a RIPEMD160. 205 | * @param {string} hex - String to hash 206 | * @returns {string} hash output 207 | */ 208 | export const sha256ripemd160 = (hex) => { 209 | if (typeof hex !== "string") throw new Error("sha256ripemd160 expects a string") 210 | if (hex.length % 2 !== 0) throw new Error(`invalid hex string length: ${hex}`) 211 | const hexEncoded = hexEncoding.parse(hex) 212 | const ProgramSha256 = SHA256(hexEncoded) 213 | return RIPEMD160(ProgramSha256).toString() 214 | } 215 | 216 | /** 217 | * Performs a single SHA256. 218 | * @param {string} hex - String to hash 219 | * @returns {string} hash output 220 | */ 221 | export const sha256 = (hex) => { 222 | if (typeof hex !== "string") throw new Error("sha256 expects a hex string") 223 | if (hex.length % 2 !== 0) throw new Error(`invalid hex string length: ${hex}`) 224 | const hexEncoded = hexEncoding.parse(hex) 225 | return SHA256(hexEncoded).toString() 226 | } 227 | 228 | -------------------------------------------------------------------------------- /src/utils/request.js: -------------------------------------------------------------------------------- 1 | import axios from "axios" 2 | /** 3 | * @alias utils.HttpRequest 4 | */ 5 | class HttpRequest { 6 | constructor(baseURL){ 7 | // this.httpClient = axios.create({ withCredentials: true, baseURL }) 8 | this.httpClient = axios.create({ baseURL }) 9 | } 10 | 11 | get(path, params, opts) { 12 | return this.request("get", path, params, opts) 13 | } 14 | 15 | post(path, body, opts) { 16 | return this.request("post", path, body, opts) 17 | } 18 | 19 | request(method, path, params, opts) { 20 | const options = { 21 | method, 22 | url: path, 23 | ...opts 24 | } 25 | 26 | if (params) { 27 | if (method === "get") { 28 | options.params = params 29 | } else { 30 | options.data = params 31 | } 32 | } 33 | 34 | return this.httpClient 35 | .request(options) 36 | .then(response => { 37 | return { result: response.data, status: response.status } 38 | }).catch(err => { 39 | // TODO: what if it's not json? 40 | console.error("error in HttpRequest#request", err) 41 | const msgObj = err.response && err.response.data && JSON.parse(err.response.data.message) 42 | let error = new Error(msgObj.message) 43 | error.code = msgObj.code 44 | error.abci_code = msgObj.abci_code 45 | throw error 46 | }) 47 | } 48 | } 49 | 50 | export default HttpRequest 51 | -------------------------------------------------------------------------------- /src/utils/validateHelper.js: -------------------------------------------------------------------------------- 1 | const MAX_INT64 = Math.pow(2, 63) 2 | 3 | /** 4 | * validate the input number. 5 | * @param {Number} value 6 | */ 7 | export const checkNumber = (value, name = "input number") => { 8 | if (value <= 0) { 9 | throw new Error(`${name} should be a positive number`) 10 | } 11 | 12 | if (MAX_INT64 <= value) { 13 | throw new Error(`${name} should be less than 2^63`) 14 | } 15 | } 16 | 17 | /** 18 | * basic validation of coins 19 | * @param {Array} coins 20 | */ 21 | export const checkCoins = (coins) => { 22 | coins = coins || [] 23 | coins.forEach((coin) => { 24 | checkNumber(coin.amount) 25 | if (!coin.denom) { 26 | throw new Error("invalid denmon") 27 | } 28 | }) 29 | } 30 | 31 | export const validateSymbol = (symbol) => { 32 | if (!symbol) { 33 | throw new Error("suffixed token symbol cannot be empty") 34 | } 35 | 36 | const splitSymbols = symbol.split("-") 37 | 38 | //check length with .B suffix 39 | if (!/^[a-zA-z\d/.]{3,10}$/.test(splitSymbols[0])) { 40 | throw new Error("symbol length is limited to 3~10") 41 | } 42 | } 43 | 44 | export const validateTradingPair = (pair) => { 45 | const symbols = pair.split("_") 46 | if (symbols.length !== 2) { 47 | throw new Error("the pair should in format \"symbol1_symbol2\"") 48 | } 49 | 50 | validateSymbol(symbols[0]) 51 | validateSymbol(symbols[1]) 52 | } 53 | 54 | export const validateOffsetLimit = (offset, limit) => { 55 | if (offset < 0) { 56 | throw new Error("offset can't be less than 0") 57 | } 58 | 59 | if (limit < 0) { 60 | throw new Error("limit can't be less than 0") 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/wallet/connector.js: -------------------------------------------------------------------------------- 1 | import WalletConnect from '@walletconnect/client'; 2 | import * as crypto from "../crypto"; 3 | 4 | const GET_ACCOUNTS = { 5 | jsonrpc: '2.0', 6 | method: 'get_accounts' 7 | }; 8 | 9 | const GET_SIGN = { 10 | jsonrpc: '2.0', 11 | method: 'okt_signTransaction' 12 | }; 13 | 14 | const EXCHAIN = /(^ex)|(^0x)/i; 15 | 16 | const ZEROX = /^0x/i; 17 | 18 | const DURING = 5000; 19 | 20 | const signType = '20'; 21 | 22 | class Connector { 23 | 24 | constructor() { 25 | this.resetConnector(); 26 | } 27 | 28 | resetConnector() { 29 | if(this.interval) clearInterval(this.interval); 30 | this.walletConnector = null; 31 | this.account = null; 32 | this.address = ''; 33 | this.interval = null; 34 | this.callback = {}; 35 | } 36 | 37 | handleConnect(accounts) { 38 | this.account = accounts[0]; 39 | } 40 | 41 | async onConnect(payload) { 42 | try { 43 | await this.getAccounts(); 44 | const { accounts } = payload.params[0]; 45 | this.handleConnect(accounts); 46 | if(!this.address) throw new Error; 47 | this.doCallback('success',{address: this.exAddress}); 48 | } catch { 49 | this.doCallback('error'); 50 | } 51 | } 52 | 53 | get exAddress() { 54 | if(ZEROX.test(this.address)) { 55 | return crypto.convertHexToBech32(this.address)[0]; 56 | } 57 | return this.address; 58 | } 59 | 60 | onDisconnect() { 61 | this.killSession(); 62 | } 63 | 64 | async getAccounts() { 65 | const walletConnector = this.walletConnector; 66 | if(!walletConnector) return ''; 67 | // this.startTimer(); 68 | let address = ''; 69 | // let timer = setTimeout(() => { 70 | // if(!address) { 71 | // console.log('获取address超时,将断开链接'); 72 | // this.killSession(); 73 | // } 74 | // }, DURING); 75 | const params = {...GET_ACCOUNTS, id: Date.now()}; 76 | console.log('get address params: ' + JSON.stringify(params)); 77 | return walletConnector.sendCustomRequest(params).then((res) => { 78 | const okexchainAccount = res.find((account) => { 79 | return EXCHAIN.test(account.address); 80 | }); 81 | if (okexchainAccount) { 82 | address = okexchainAccount.address; 83 | this.address = address; 84 | } 85 | if(!address) throw new Error('get address failed'); 86 | return this.address 87 | }).catch(() => { 88 | // console.log('获取address失败,将断开链接'); 89 | // this.killSession(); 90 | }).finally(() => { 91 | // clearTimeout(timer); 92 | }); 93 | } 94 | 95 | async startTimer() { 96 | if(this.startTimer.interval) return; 97 | this.startTimer.interval = setInterval(() => { 98 | console.log('get address'); 99 | this.getAccounts(); 100 | }, DURING); 101 | } 102 | 103 | async subscribeToEvents() { 104 | const walletConnector = this.walletConnector; 105 | if (!walletConnector) { 106 | return; 107 | } 108 | walletConnector.on('call_request', (error, payload) => { 109 | console.log('call_request', payload, error); 110 | if (error) { 111 | throw error; 112 | } 113 | }); 114 | 115 | walletConnector.on('connect', (error, payload) => { 116 | console.log('connect', payload); 117 | if (error) { 118 | throw error; 119 | } 120 | this.onConnect(payload); 121 | }); 122 | 123 | walletConnector.on('disconnect', (error, payload) => { 124 | console.log('disconnect', payload); 125 | this.onDisconnect(); 126 | if (error) { 127 | throw error; 128 | } 129 | }); 130 | 131 | walletConnector.on('session_request',(error, payload) => { 132 | console.log('session_request', payload); 133 | if (error) { 134 | throw error; 135 | } 136 | }); 137 | 138 | if (walletConnector.connected) { 139 | const { accounts } = walletConnector; 140 | this.handleConnect(accounts); 141 | } 142 | } 143 | 144 | async createSession() { 145 | const walletConnector = this.walletConnector; 146 | if(!walletConnector) return; 147 | await walletConnector.createSession(); 148 | } 149 | 150 | async walletConnectInit(storageId) { 151 | const bridge = 'wss://bridge.walletconnect.org'; 152 | const walletConnector = new WalletConnect({ bridge }); 153 | walletConnector._clientMeta.name = 'ΟKEx DEX'; 154 | walletConnector._clientMeta.url = walletConnector._clientMeta.url.replace(/okex/i,'οkex'); 155 | if(storageId) walletConnector._sessionStorage.storageId = storageId; 156 | this.walletConnector = walletConnector; 157 | 158 | this.subscribeToEvents(); 159 | 160 | if (!walletConnector.connected || !walletConnector.uri) { 161 | console.log('create session'); 162 | await this.createSession(); 163 | } else { 164 | await this.getAccounts(); 165 | } 166 | } 167 | 168 | killSession(callback) { 169 | const walletConnector = this.walletConnector; 170 | if (walletConnector && walletConnector.connected) { 171 | walletConnector.killSession(); 172 | } 173 | if(callback) callback(); 174 | else this.doCallback('sessionCancel'); 175 | this.resetConnector(); 176 | } 177 | 178 | setCallback(callback={}) { 179 | this.callback = callback; 180 | } 181 | 182 | doCallback(type,params) { 183 | if(typeof this.callback[type] === 'function' )this.callback[type](params); 184 | } 185 | 186 | async getSession(callback, storageId) { 187 | this.setCallback(callback); 188 | let session = ''; 189 | try { 190 | if(!this.walletConnector || !this.walletConnector.uri) { 191 | await this.walletConnectInit(storageId); 192 | } 193 | session = this.walletConnector.uri; 194 | } finally { 195 | if(!session) { 196 | console.log('初始链接失败') 197 | this.killSession(); 198 | } 199 | else this.doCallback('sessionSuccess'); 200 | } 201 | return session; 202 | } 203 | 204 | sendSignMsg(signMsg) { 205 | const params = {...GET_SIGN,params:[signMsg],id:Date.now()}; 206 | console.log('发送签名数据',JSON.stringify(params)); 207 | return this.walletConnector.sendCustomRequest(params).catch(() => console.log('签名失败')); 208 | } 209 | 210 | async sign(signMsg) { 211 | return this.sendSignMsg(signMsg).then(res => { 212 | res = JSON.parse(res); 213 | return res.tx.signatures; 214 | }); 215 | } 216 | 217 | async sign4Token(signMsg) { 218 | signMsg = {...signMsg, signType}; 219 | return this.sendSignMsg({ 220 | data: JSON.stringify(signMsg) 221 | }).then(res => ({rawTransaction: res})); 222 | } 223 | } 224 | 225 | export default new Connector(); 226 | -------------------------------------------------------------------------------- /src/wallet/index.js: -------------------------------------------------------------------------------- 1 | import connector from './connector'; 2 | 3 | /** 4 | * {sessionSuccess,sessionFail,sessionCancel,success,error} 5 | * @param {*} callbacks 6 | */ 7 | export function getSession(callback={}, storageId) { 8 | return connector.getSession(callback, storageId); 9 | } 10 | 11 | export function killSession() { 12 | return connector.killSession(); 13 | } 14 | 15 | export async function getAddress() { 16 | let address = connector.exAddress; 17 | try { 18 | if(!address) { 19 | await connector.getAccounts(); 20 | address = connector.exAddress; 21 | } 22 | } catch { 23 | console.log('get address fail'); 24 | } 25 | return address; 26 | } 27 | 28 | export function sign(signMsg) { 29 | return connector.sign(signMsg); 30 | } 31 | 32 | export function sign4Token(signMsg) { 33 | return connector.sign4Token(signMsg); 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /version-mapping.md: -------------------------------------------------------------------------------- 1 | | javascript-sdk github commitID | javascript-sdk npm version | okexchain version | 2 | | ----------------------------- | -------------------------------- | ----------------- | 3 | | 5dba750d33483003238817a629f4df5605bfd438 | @okexchain/javascript-sdk@0.0.20 | v0.16.0 | 4 | | v0.16.0 | @okexchain/javascript-sdk@0.0.19 | v0.16.0 | 5 | | | | | 6 | --------------------------------------------------------------------------------