diff --git a/__tests__/client.test.js b/__tests__/client.test.js index 805232a..3ce5796 100644 --- a/__tests__/client.test.js +++ b/__tests__/client.test.js @@ -4,11 +4,14 @@ import * as crypto from "../src/crypto" const mnemonic = "total lottery arena when pudding best candy until army spoil drill pool" -const privateKey = "29892b64003fc5c8c89dc795a2ae82aa84353bb4352f28707c2ed32aa1011884" -const fromAddress = "okexchain1pt7xrmxul7sx54ml44lvv403r06clrdkgmvr9g" -const serverUrl = "http://localhost:8545" +const privateKey_996 = "29892b64003fc5c8c89dc795a2ae82aa84353bb4352f28707c2ed32aa1011884" +const privateKey = "828e61f969a7369f3340b07dd2080740d8445d7f802899ddacf9bc4db8608997" +const from_996 = "okexchain1pt7xrmxul7sx54ml44lvv403r06clrdkgmvr9g" +const from = "okexchain1ya7dn2rr8nx07tx9ksq8gvz5utvarrh03cen3l" +const serverUrl = "https://exchaintest.okexcn.com" +// const serverUrl = "https://exchaintest.okexcn.com" const userAddress = "okexchain1jjvpmgwwgs99nhlje3aag0lackunqgj7xnrnwe" -const chainId = "okexchain-1" // -testnet1 +const chainId = "okexchain-65" // -testnet1 const baseCoin = "okt" const testCoin = "xxb-781" const testProduct = testCoin + "_" + baseCoin @@ -21,11 +24,14 @@ describe("OKEXChainClient test", async () => { it("get balance", async () => { const client = new OKEXChainClient(serverUrl, { - chainId: chainId + chainId: chainId, + relativePath: "/okexchain-test/v1", + isMainnet: false }) - const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic) + const privateKey = crypto.getPrivateKeyFromMnemonic(mnemonic, '60') await client.setAccountInfo(privateKey) - const res = await client.getBalance(fromAddress) + const res = await client.getBalance(from) + console.log(res) expect(res.length).toBeGreaterThanOrEqual(0) }) diff --git a/docs/okexchain-jssdk-doc-crypto.md b/docs/okexchain-jssdk-doc-crypto.md index c9e0609..6c73db4 100644 --- a/docs/okexchain-jssdk-doc-crypto.md +++ b/docs/okexchain-jssdk-doc-crypto.md @@ -8,6 +8,8 @@ * [.decodeAddressToBuffer](#module_crypto.decodeAddressToBuffer) * [.validateAddress](#module_crypto.validateAddress) ⇒ boolean * [.encodeAddressToBech32](#module_crypto.encodeAddressToBech32) ⇒ string + * [.convertBech32ToHex](#module_crypto.convertBech32ToHex) ⇒ String + * [.convertHexToBech32](#module_crypto.convertHexToBech32) ⇒ string * [.generatePrivateKey](#module_crypto.generatePrivateKey) ⇒ string * [.getPubKeyFromHex](#module_crypto.getPubKeyFromHex) ⇒ Elliptic.PublicKey * [.encodePubKeyToCompressedBuffer](#module_crypto.encodePubKeyToCompressedBuffer) ⇒ Buffer @@ -76,6 +78,28 @@ Encodes address from hex to bech32 format. | hexAddr | string | address in hex string | | prefix | string | address prefix | + + +### crypto.convertBech32ToHex ⇒ String +covert okexchain address to 0x address + +**Kind**: static constant of [crypto](#module_crypto) + +| Param | +| --- | +| bech32Address | + + + +### crypto.convertHexToBech32 ⇒ string +covert 0x address to okexchain address + +**Kind**: static constant of [crypto](#module_crypto) + +| Param | +| --- | +| hexAddress | + ### crypto.generatePrivateKey ⇒ string diff --git a/package-lock.json b/package-lock.json index 3ff539a..a765b9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -774,6 +774,22 @@ "to-fast-properties": "^2.0.0" } }, + "@json-rpc-tools/types": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/@json-rpc-tools/types/-/types-1.6.4.tgz", + "integrity": "sha512-DHtnvlIFN8YUun38Sy9SaRdV/BsUMFM5bAABDsb/iPGLfPHOMKoAyuPOwEqQ2vgtc9ayTcQ2546OPTQ92IzJ/g==", + "requires": { + "keyvaluestorage-interface": "^1.0.0" + } + }, + "@json-rpc-tools/utils": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@json-rpc-tools/utils/-/utils-1.6.1.tgz", + "integrity": "sha512-cNwP4QapAls+xATU8zLLqPYa9qCbgwEyWEK7vE1oH91b3LfbUYwHtiWZ1+rv0X/mh/9cWNTo2Oi2Sah/QX0WwA==", + "requires": { + "@json-rpc-tools/types": "^1.6.1" + } + }, "@json-schema-spec/json-pointer": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@json-schema-spec/json-pointer/-/json-pointer-0.1.2.tgz", @@ -792,6 +808,26 @@ "uri-js": "^4.2.2" } }, + "@pedrouid/iso-crypto": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pedrouid/iso-crypto/-/iso-crypto-1.1.0.tgz", + "integrity": "sha512-twi+tW67XT0BSOv4rsegnGo4TQMhfFswS/GY3KhrjFiNw3z9x+cMkfO+itNe1JZghQxsxHuhifvfsnG814g1hQ==", + "requires": { + "@pedrouid/iso-random": "^1.1.0", + "aes-js": "^3.1.2", + "enc-utils": "^3.0.0", + "hash.js": "^1.1.7" + } + }, + "@pedrouid/iso-random": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pedrouid/iso-random/-/iso-random-1.1.0.tgz", + "integrity": "sha512-U8P2qdbvyU5aom0036dkpp0C9c8pgW1SNhAo8+zPDzgmKA58Hl6dc+ZkQXkE9aHrzN6v/0w+409JMjSYwx5tVw==", + "requires": { + "enc-utils": "^3.0.0", + "randombytes": "^2.1.0" + } + }, "@types/deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/deep-equal/-/deep-equal-1.0.1.tgz", @@ -804,6 +840,93 @@ "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", "dev": true }, + "@walletconnect/client": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@walletconnect/client/-/client-1.3.3.tgz", + "integrity": "sha512-aHwsX2lvdEhb2OutHr0cKKRNMOAhaE/Xejbk6stbUozeh0MKAWwhVW5g16xd+wX07Mictq4JFQrg3dSsabRJlg==", + "requires": { + "@walletconnect/core": "^1.3.3", + "@walletconnect/iso-crypto": "^1.3.3", + "@walletconnect/types": "^1.3.3", + "@walletconnect/utils": "^1.3.3" + } + }, + "@walletconnect/core": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-1.3.6.tgz", + "integrity": "sha512-1HHP2xZI6b88WQgszs3gP5xkkCwwlWgDJz+J6ADGzVXhQP21p1mZhKezUtx27rOtQimMIrPDfgPyAHwQBZkkSw==", + "requires": { + "@walletconnect/socket-transport": "^1.3.6", + "@walletconnect/types": "^1.3.6", + "@walletconnect/utils": "^1.3.6" + } + }, + "@walletconnect/iso-crypto": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@walletconnect/iso-crypto/-/iso-crypto-1.3.6.tgz", + "integrity": "sha512-HypXNSmMAuEvNhllXWsCHtCVK4JfFFcZqPijurcXmOtWanjZV+8NuiYnKG11qAllSbYRwqKchb7GTDp33n0g0Q==", + "requires": { + "@pedrouid/iso-crypto": "^1.0.0", + "@walletconnect/types": "^1.3.6", + "@walletconnect/utils": "^1.3.6" + } + }, + "@walletconnect/socket-transport": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@walletconnect/socket-transport/-/socket-transport-1.3.6.tgz", + "integrity": "sha512-dvO8mRECU4I6FpoQX9GMh9BNzR2/g6vcj9LEIjgApW6Rfx0mCKUgoVBSi2W7NHC94zfdYiJdaH950oismj5gNw==", + "requires": { + "@walletconnect/types": "^1.3.6", + "@walletconnect/utils": "^1.3.6", + "ws": "7.3.0" + }, + "dependencies": { + "ws": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", + "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==" + } + } + }, + "@walletconnect/types": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-1.3.6.tgz", + "integrity": "sha512-fNir3Pi1ZpuVlgNr8qtP2LOSsV9rNgJGHmBnHHqKNmpuRpPxG1mhmKFdDHNGyVIP5bM5CWIXmlULDTax63UJbg==" + }, + "@walletconnect/utils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-1.3.6.tgz", + "integrity": "sha512-nzTO5A3Ltjrsu6u8SR/KqdHTH03848KIj5MQlOCUjwxW1fXOvuri8+kwFKqlMn0bk1Qvlt6rrOptbt14PW8kSA==", + "requires": { + "@json-rpc-tools/utils": "1.6.1", + "@walletconnect/types": "^1.3.6", + "bn.js": "4.11.8", + "detect-browser": "5.1.0", + "enc-utils": "3.0.0", + "js-sha3": "0.8.0", + "query-string": "6.13.5", + "safe-json-utils": "1.0.0", + "window-getters": "1.0.0", + "window-metadata": "1.0.0" + }, + "dependencies": { + "query-string": { + "version": "6.13.5", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.13.5.tgz", + "integrity": "sha512-svk3xg9qHR39P3JlHuD7g3nRnyay5mHbrPctEBDUxUkHRifPHXJDhBUycdCC0NBjXoDf44Gb+IsOZL1Uwn8M/Q==", + "requires": { + "decode-uri-component": "^0.2.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" + } + } + }, "JSONStream": { "version": "1.3.5", "resolved": "http://registry.npm.taobao.org/JSONStream/download/JSONStream-1.3.5.tgz", @@ -890,6 +1013,11 @@ "integrity": "sha1-02O2b1+sXwGP+cOh57b44xDMORM=", "dev": true }, + "aes-js": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz", + "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==" + }, "ajv": { "version": "6.10.0", "resolved": "http://registry.npm.taobao.org/ajv/download/ajv-6.10.0.tgz", @@ -3026,6 +3154,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" }, + "detect-browser": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.1.0.tgz", + "integrity": "sha512-WKa9p+/MNwmTiS+V2AS6eGxic+807qvnV3hC+4z2GTY+F42h1n8AynVTMMc4EJBC32qMs6yjOTpeDEQQt/AVqQ==" + }, "detect-indent": { "version": "4.0.0", "resolved": "http://registry.npm.taobao.org/detect-indent/download/detect-indent-4.0.0.tgz", @@ -3189,6 +3322,15 @@ "integrity": "sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY=", "dev": true }, + "enc-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/enc-utils/-/enc-utils-3.0.0.tgz", + "integrity": "sha512-e57t/Z2HzWOLwOp7DZcV0VMEY8t7ptWwsxyp6kM2b2zrk6JqIpXxzkruHAMiBsy5wg9jp/183GdiRXCvBtzsYg==", + "requires": { + "is-typedarray": "1.0.0", + "typedarray-to-buffer": "3.1.5" + } + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -6780,6 +6922,11 @@ "integrity": "sha1-+IxgjjJKM3OpW8xFrTBeXJecRZs=", "dev": true }, + "js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "js-tokens": { "version": "4.0.0", "resolved": "http://registry.npm.taobao.org/js-tokens/download/js-tokens-4.0.0.tgz", @@ -7015,6 +7162,11 @@ "node-gyp-build": "^4.2.0" } }, + "keyvaluestorage-interface": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz", + "integrity": "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==" + }, "kind-of": { "version": "6.0.2", "resolved": "http://registry.npm.taobao.org/kind-of/download/kind-of-6.0.2.tgz", @@ -8808,6 +8960,11 @@ "resolved": "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz", "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" }, + "safe-json-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-json-utils/-/safe-json-utils-1.0.0.tgz", + "integrity": "sha512-n0hJm6BgX8wk3G+AS8MOQnfcA8dfE6ZMUfwkHUNx69YxPlU3HDaZTHXWto35Z+C4mOjK1odlT95WutkGC+0Idw==" + }, "safe-regex": { "version": "1.1.0", "resolved": "http://registry.npm.taobao.org/safe-regex/download/safe-regex-1.1.0.tgz", @@ -9309,6 +9466,11 @@ "integrity": "sha1-dezRqI3owYTvAV6vtRtbSL/RG7E=", "dev": true }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" + }, "split-string": { "version": "3.1.0", "resolved": "http://registry.npm.taobao.org/split-string/download/split-string-3.1.0.tgz", @@ -10006,6 +10168,14 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, "typeforce": { "version": "1.18.0", "resolved": "http://registry.npm.taobao.org/typeforce/download/typeforce-1.18.0.tgz", @@ -10454,6 +10624,19 @@ "bs58check": "<3.0.0" } }, + "window-getters": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/window-getters/-/window-getters-1.0.0.tgz", + "integrity": "sha512-xyvEFq3x+7dCA7NFhqOmTMk0fPmmAzCUYL2svkw2LGBaXXQLRP0lFnfXHzysri9WZNMkzp/FD1u0w2Qc7Co+JA==" + }, + "window-metadata": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/window-metadata/-/window-metadata-1.0.0.tgz", + "integrity": "sha512-eYoXsZ9X4J+6xZgbHhNAatSR5bCtT409q8B+2Ol9ySx7qsdtgVZcNfox4qszFmKlGsFtT2b1Tcmcy69bRMObcg==", + "requires": { + "window-getters": "^1.0.0" + } + }, "wordwrap": { "version": "1.0.0", "resolved": "http://registry.npm.taobao.org/wordwrap/download/wordwrap-1.0.0.tgz", diff --git a/package.json b/package.json index 0ab3e25..fc2627f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@okexchain/javascript-sdk", - "version": "0.0.31", + "version": "0.0.32", "license": "Apache-2.0", "main": "lib/index.js", "scripts": { @@ -13,6 +13,7 @@ "sdk": "webpack-dev-server --config build/webpack.config.sdk.js" }, "dependencies": { + "@walletconnect/client": "1.3.3", "axios": "^0.18.0", "babel-polyfill": "^6.26.0", "base32-encode": "^1.1.0", diff --git a/src/client.js b/src/client.js index 92d8a97..3dbd421 100644 --- a/src/client.js +++ b/src/client.js @@ -7,6 +7,7 @@ import * as crypto from "./crypto" import Transaction from "./transaction" import HttpProxy from "./httpProxy" +import * as wallet from './wallet' const defaultChainId = "okexchain-66" const defaultRelativePath = "/okexchain/v1" @@ -107,6 +108,12 @@ export class OKEXChainClient { * @return {OKEXChainClient} */ async setAccountInfo(privateKey) { + if(!privateKey) { + const address = await wallet.getAddress(); + if (!address) throw new Error("invalid privateKey: " + privateKey) + await this.setAccountInfoByWallet(address); + return this; + } if (privateKey !== this.privateKey) { const address = crypto.getAddressFromPrivateKey(privateKey, bech32Head) if (!address) throw new Error("invalid privateKey: " + privateKey) @@ -119,6 +126,17 @@ export class OKEXChainClient { return this } + /** + * @return {OKEXChainClient} + */ + async setAccountInfoByWallet(address) { + if (!address) throw new Error("invalid wallet connect address: " + address); + if (address === this.address) return this + this.address = address + const data = await this.getAccount(address) + this.account_number = this.getAccountNumberFromAccountInfo(data) + return this + } /** * Send SendTransaction. @@ -283,7 +301,7 @@ export class OKEXChainClient { return await tx.sign(this.signer, signMsg, this.address); } else { - return tx.sign(this.privateKey, signMsg) + return this.privateKey ? tx.sign(this.privateKey, signMsg) : tx.signByWallet(signMsg) } } diff --git a/src/crypto/index.js b/src/crypto/index.js index b758fdb..4d0337f 100644 --- a/src/crypto/index.js +++ b/src/crypto/index.js @@ -77,11 +77,21 @@ export const encodeAddressToBech32 = (hexAddr, prefix = "okexchain") => { function buf2hex(buffer) { // buffer is an ArrayBuffer return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join(''); } + +/** + * covert okexchain address to 0x address + * @param bech32Address + * @returns {String} + */ export const convertBech32ToHex = (bech32Address) => { const address = decodeAddressToBuffer(bech32Address) return toChecksumAddress("0x"+buf2hex(address)) } - +/** + * covert 0x address to okexchain address + * @param hexAddress + * @returns {string} + */ export const convertHexToBech32 = (hexAddress) => { return encodeAddressToBech32(hexAddress.toLowerCase()) } diff --git a/src/index.js b/src/index.js index 583b1ab..fa7c6df 100644 --- a/src/index.js +++ b/src/index.js @@ -1,8 +1,11 @@ import "babel-polyfill" import * as client from "./client" import * as crypto from "./crypto" +import * as wallet from "./wallet" const { OKEXChainClient } = client module.exports = OKEXChainClient -module.exports.crypto = crypto +module.exports.crypto = crypto; +module.exports.wallet = wallet; + diff --git a/src/transaction.js b/src/transaction.js index 3081ed2..799acf1 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -1,5 +1,5 @@ import * as crypto from "./crypto/" - +import * as wallet from "./wallet" /** * Transaction @@ -67,6 +67,33 @@ class Transaction { return this } + /** + * @param {Object} msg + * @return {Transaction} + **/ + async signByWallet(msg) { + + const signMsg = { + to: '', + symbol: 'OKT', + memo: this.memo, + // contractAddress:'', + decimalNum: '0', + accountNumber:this.account_number.toString(), + sequenceNumber:this.sequence.toString(), + value: '0', + gasLimit: this.fee.gas, + gasPrice: this.fee.amount[0].amount, + data: JSON.stringify(msg) + } + + console.log("signmsg: ",JSON.stringify(signMsg)) + + this.signatures = await wallet.sign(signMsg); + + return this + } + /** * @param {string} mode * @return {Object} diff --git a/src/wallet/connector.js b/src/wallet/connector.js new file mode 100644 index 0000000..04acc20 --- /dev/null +++ b/src/wallet/connector.js @@ -0,0 +1,210 @@ +import WalletConnect from '@walletconnect/client'; + +const GET_ACCOUNTS = { + jsonrpc: '2.0', + method: 'get_accounts' +}; + +const GET_SIGN = { + jsonrpc: '2.0', + method: 'okt_signTransaction' +}; + +const OKEXCHAIN = 'okexchain'; + +// const DURING = 5000; + +class Connector { + + constructor() { + this.resetConnector(); + } + + resetConnector() { + if(this.interval) clearInterval(this.interval); + this.walletConnector = null; + this.account = null; + this.address = ''; + this.interval = null; + this.callback = {}; + } + + handleConnect(accounts) { + this.account = accounts[0]; + } + + async onConnect(payload) { + try { + await this.getAccounts(); + const { accounts } = payload.params[0]; + this.handleConnect(accounts); + if(!this.address) throw new Error; + this.doCallback('success',{address: this.address}); + } catch { + this.doCallback('error'); + } + } + + onDisconnect() { + this.killSession(); + } + + async getAccounts() { + const walletConnector = this.walletConnector; + if(!walletConnector) return ''; + // this.startTimer(); + return new Promise((resolve,reject) => { + let address = ''; + // let timer = setTimeout(() => { + // if(!address) { + // console.log('获取address超时,将断开链接'); + // this.killSession(); + // } + // }, DURING); + const params = {...GET_ACCOUNTS, id: Date.now()}; + console.log('get address params: ' + JSON.stringify(params)); + walletConnector.sendCustomRequest(params).then((res) => { + const okexchainAccount = res.find((account) => { + return account.address.startsWith(OKEXCHAIN); + }); + if (okexchainAccount) { + address = okexchainAccount.address; + this.address = address; + } + if(!address) throw new Error('get address failed'); + resolve(this.address); + }).catch(err => { + // console.log('获取address失败,将断开链接'); + // this.killSession(); + reject(err); + }).finally(() => { + // clearTimeout(timer); + }); + }); + } + + async startTimer() { + if(this.startTimer.interval) return; + this.startTimer.interval = setInterval(() => { + console.log('get address'); + this.getAccounts(); + }, DURING); + } + + async subscribeToEvents() { + const walletConnector = this.walletConnector; + if (!walletConnector) { + return; + } + walletConnector.on('call_request', (error, payload) => { + console.log('call_request', payload, error); + if (error) { + throw error; + } + }); + + walletConnector.on('connect', (error, payload) => { + console.log('connect', payload); + if (error) { + throw error; + } + this.onConnect(payload); + }); + + walletConnector.on('disconnect', (error, payload) => { + console.log('disconnect', payload); + this.onDisconnect(); + if (error) { + throw error; + } + }); + + walletConnector.on('session_request',(error, payload) => { + console.log('session_request', payload); + if (error) { + throw error; + } + }); + + if (walletConnector.connected) { + const { accounts } = walletConnector; + this.handleConnect(accounts); + } + } + + async createSession() { + const walletConnector = this.walletConnector; + if(!walletConnector) return; + await walletConnector.createSession(); + } + + async walletConnectInit() { + const bridge = 'wss://bridge.walletconnect.org'; + const walletConnector = new WalletConnect({ bridge }); + walletConnector._clientMeta.name = 'ΟKEx DEX'; + walletConnector._clientMeta.url = walletConnector._clientMeta.url.replace(/okex/i,'οkex'); + this.walletConnector = walletConnector; + + this.subscribeToEvents(); + + if (!walletConnector.connected || !walletConnector.uri) { + console.log('create session'); + await this.createSession(); + } else { + await this.getAccounts(); + } + } + + killSession(callback) { + const walletConnector = this.walletConnector; + if (walletConnector && walletConnector.connected) { + walletConnector.killSession(); + } + if(callback) callback(); + else this.doCallback('sessionCancel'); + this.resetConnector(); + } + + setCallback(callback={}) { + this.callback = callback; + } + + doCallback(type,params) { + if(typeof this.callback[type] === 'function' )this.callback[type](params); + } + + async getSession(callback) { + this.setCallback(callback); + let session = ''; + try { + if(!this.walletConnector || !this.walletConnector.uri) { + await this.walletConnectInit(); + } + session = this.walletConnector.uri; + } finally { + if(!session) { + console.log('初始链接失败') + this.killSession(); + } + else this.doCallback('sessionSuccess'); + } + return session; + } + + async sign(signMsg) { + return new Promise((resolve,reject) => { + const params = {...GET_SIGN,params:[signMsg],id:Date.now()}; + console.log('发送签名数据',JSON.stringify(params)); + this.walletConnector.sendCustomRequest(params).then((res) => { + res = JSON.parse(res); + console.log(res); + resolve(res.tx.signatures); + }).catch(err => { + console.log('签名失败') + reject(err); + }); + }); + } +} + +export default new Connector(); diff --git a/src/wallet/index.js b/src/wallet/index.js new file mode 100644 index 0000000..22390f4 --- /dev/null +++ b/src/wallet/index.js @@ -0,0 +1,29 @@ +import connector from './connector'; + +/** + * {sessionSuccess,sessionFail,sessionCancel,success,error} + * @param {*} callbacks + */ +export function getSession(callback={}) { + return connector.getSession(callback); +} + +export function killSession() { + return connector.killSession(); +} + +export async function getAddress() { + let address = connector.address; + try { + if(!address) address = await connector.getAccounts(); + } catch { + console.log('get address fail'); + } + return address; +} + +export function sign(signMsg) { + return connector.sign(signMsg); +} + +