diff --git a/src/JCWallet.d.ts b/src/JCWallet.d.ts index 7b9d586..3550d3f 100644 --- a/src/JCWallet.d.ts +++ b/src/JCWallet.d.ts @@ -26,24 +26,19 @@ declare namespace jsb { export function showWebPage(url: string); export function openURL(url: string); export function scanQRCode(id: number, title: string); - export function restoreKey(id: number, oid: string); - export function generateWallet(idHash: string, seedHash: string); export function hexDeflate(str: string): string; export function hexInflate(str: string): string; - export function encryptedLocalKey(pk: string): string; + export function storeLocalPass(pass: string): void; + export function verifyLocalPass(pass: string): boolean; export function walletEncrypt(str: string): string; export function walletDecrypt(str: string): string; export function prepareWallet( - idHash: string, - seedHash: string, - key_master: string - ); - export function restoreWallet( - idHash: string, - seedHash: string, + id: string, + openid: string, key_master: string, - key_restore: any - ); + salt: string, + pass: string + ): { address: string }; } declare let window: Window; diff --git a/src/config/WalletEnv.ts b/src/config/WalletEnv.ts index e1c2aa8..b6783a2 100644 --- a/src/config/WalletEnv.ts +++ b/src/config/WalletEnv.ts @@ -3,7 +3,21 @@ import { singleton } from "../decorator/singleton.decorator"; @singleton export class WalletEnv { - public idToken: string; public token: string; + public address: string; + public key: string; + public salt: string; + public handler = createWalletEvents(); + + public get tokenData(): any { + if (!this.token) { + return {}; + } + let datas = this.token.split("."); + if (datas.length < 2) { + return {}; + } + return window.atob(datas[1]); + } } diff --git a/src/index.ts b/src/index.ts index d8b1967..c08d11e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -27,6 +27,7 @@ import { parseUrl } from "./manage/SchemeManage"; import { loadInternalWallet, restoreWalletByMnemonic, + walletPreLogin, } from "./manage/WalletManage"; import { EmailVerifySvr } from "./services/EmailVerifySvr"; import { NativeSvr } from "./services/NativeSvr"; @@ -107,9 +108,14 @@ export default class JCWallet { return this.walletType === WalletType.INTERNAL; } - public async initInternalWallet(channel: number) { + public async preLogin(channel: number) { + let token = await walletPreLogin(channel); + return token; + } + + public async initInternalWallet(pass: string) { this.walletType = WalletType.INTERNAL; - let address: string = await loadInternalWallet(channel); + let address: string = await loadInternalWallet(pass); this.nativeAccount = address; console.log("native wallet address: " + address); var start = Date.now(); diff --git a/src/manage/WalletManage.ts b/src/manage/WalletManage.ts index ed0ecaf..ed29533 100644 --- a/src/manage/WalletManage.ts +++ b/src/manage/WalletManage.ts @@ -16,6 +16,7 @@ import { WalletEnv } from "../config/WalletEnv"; import { md5Hash, sha1Hash } from "../util/crypto.util"; import { retry } from "../util/promise.util"; import { MAX_TRY_COUNT, MAX_UPLOAD_COUNT } from "../config/constants"; +import { ZError } from "../common/ZError"; export function newAccount(password: string, index: number) { const mnemonic = loadMnemonic(password); @@ -39,7 +40,19 @@ export function restoreWalletByMnemonic(mnemonic: string, password: string) { saveMnemonic(mnemonic, password); } -export async function loadInternalWallet(channel: number) { +async function syncWalletEnv() { + let walletEnv = new WalletEnv(); + let infoRes = await retry(() => getWalletInfo(), MAX_TRY_COUNT); + if (infoRes.errcode) { + throw new ZError(infoRes.errcode, infoRes.errmsg); + } + walletEnv.address = infoRes.data.address; + walletEnv.key = infoRes.data.key; + walletEnv.salt = infoRes.data.salt; +} + +export async function walletPreLogin(channel: number) { + let walletEnv = new WalletEnv(); let tokenRes: any; if (channel == 1) { let res: any = await new NativeSvr().signWithApple(); @@ -69,61 +82,38 @@ export async function loadInternalWallet(channel: number) { window.debug && console.log("wallet token: " + tokenRes.data?.token); window.debug && console.log(tokenRes); if (tokenRes.errcode || !tokenRes.data?.token) { - return; + throw new ZError(tokenRes.errcode, tokenRes.errmsg); + } + walletEnv.token = tokenRes.data.token; + await syncWalletEnv(); + return { token: walletEnv.token, address: walletEnv.address }; +} + +export async function loadInternalWallet(pass: string) { + let walletEnv = new WalletEnv(); + if (!walletEnv.key) { + await syncWalletEnv(); + } + if (!walletEnv.address) { + walletEnv.address; } - new WalletEnv().token = tokenRes.data.token; - let infoRes = await retry(() => getWalletInfo(), MAX_TRY_COUNT); - if (infoRes.errcode) { - return; + let { id, openid } = walletEnv.tokenData; + let { address } = jsb.prepareWallet( + id, + openid, + walletEnv.key, + walletEnv.salt, + pass + ); + if (walletEnv.address && walletEnv.address !== address) { + throw new ZError(10, "address not match, perhaps wrong password"); } - let seed = infoRes.data.oid + infoRes.data.is + infoRes.data.salt; - let seedHash = md5Hash(seed); - let address; - let idHash = md5Hash(infoRes.data.oid); - if (!infoRes.data.key) { - let time = Date.now(); - let strWallet = jsb.generateWallet(idHash, seedHash); - console.log("generate wallet cost: " + (Date.now() - time) / 1000); - window.debug && console.log("native wallet info " + strWallet); - let walletInfo = JSON.parse(strWallet); - address = walletInfo.address; - // setImmediate(function () { - - // }); - retry( - () => uploadWalletInfo({ key: walletInfo.master, address }), - MAX_UPLOAD_COUNT - ); - } else { - let localSKey, localBKey; - if (jsb.loadLocalStorage) { - localSKey = jsb.loadLocalStorage("cebg_wallet_s_" + idHash); - localBKey = jsb.loadLocalStorage("cebg_wallet_b_" + idHash); - } else { - localSKey = localStorage.getItem("cebg_wallet_s_" + idHash); - localBKey = localStorage.getItem("cebg_wallet_b_" + idHash); - } - - if (localSKey || localBKey) { - let strWallet = jsb.prepareWallet(idHash, seedHash, infoRes.data.key); - let walletInfo = JSON.parse(strWallet); - address = walletInfo.address; - retry(() => uploadWalletInfo({ address }), MAX_UPLOAD_COUNT); - } else { - let qrResult = await new NativeSvr().restoreKey(idHash); - let strWallet = jsb.restoreWallet( - idHash, - seedHash, - infoRes.data.key, - qrResult - ); - window.debug && console.log("restore native wallet info " + strWallet); - let walletInfo = JSON.parse(strWallet); - address = walletInfo.address; - retry(() => uploadWalletInfo({ address }), MAX_UPLOAD_COUNT); - } + if (!walletEnv.address) { + retry(() => uploadWalletInfo({ address }), MAX_UPLOAD_COUNT); } + walletEnv.address = address; + jsb.storeLocalPass(pass); return address; } @@ -134,16 +124,16 @@ export function walletSign(str: string) { export async function parseWebLogin(dataStr: string) { console.log("found web login scheme, begin login"); - if (dataStr.indexOf("|") < 0) { - return; - } - let datas = dataStr.split("|"); - let webtoken = datas[0]; - let pk64 = datas[1]; - let pk = jsb.hexInflate(pk64); - let keyEncrypt = jsb.encryptedLocalKey(pk); - console.log("webtoken: " + webtoken); - console.log("local key: " + keyEncrypt); - let result = await uploadInfoForWebLogin({ key: keyEncrypt, webtoken }); - console.log("login result: " + result); + // if (dataStr.indexOf("|") < 0) { + // return; + // } + // let datas = dataStr.split("|"); + // let webtoken = datas[0]; + // let pk64 = datas[1]; + // let pk = jsb.hexInflate(pk64); + // let keyEncrypt = jsb.encryptedLocalKey(pk); + // console.log("webtoken: " + webtoken); + // console.log("local key: " + keyEncrypt); + // let result = await uploadInfoForWebLogin({ key: keyEncrypt, webtoken }); + // console.log("login result: " + result); } diff --git a/src/services/NativeSvr.ts b/src/services/NativeSvr.ts index c62eef9..1e44ad2 100644 --- a/src/services/NativeSvr.ts +++ b/src/services/NativeSvr.ts @@ -75,10 +75,4 @@ export class NativeSvr { jsb.scanQRCode(id, title); return this._subscribeToCallResponse(id); } - - public restoreKey(oid: string) { - let id = payloadId(); - jsb.restoreKey(id, oid); - return this._subscribeToCallResponse(id); - } }