UNPKG

@pgchain/blockchain-libs

Version:
279 lines 13 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Provider = void 0; const conflux_address_js_1 = require("@conflux-dev/conflux-address-js"); const abi_1 = require("@ethersproject/abi"); const bytes_1 = require("@ethersproject/bytes"); const keccak256_1 = require("@ethersproject/keccak256"); const js_sdk_1 = __importDefault(require("@onekeyfe/js-sdk")); const bignumber_js_1 = __importDefault(require("bignumber.js")); const ethUtil = __importStar(require("ethereumjs-util")); // @ts-ignore: has no exported member 'PersonalMessage' const js_conflux_sdk_1 = require("js-conflux-sdk"); const bignumber_plus_1 = require("../../../basic/bignumber-plus"); const precondtion_1 = require("../../../basic/precondtion"); const abc_1 = require("../../abc"); const message_1 = require("../eth/sdk/message"); const conflux_1 = require("./conflux"); function hashCfxMessage(typedMessage) { const { type, message } = typedMessage; switch (type) { case undefined: case message_1.MessageTypes.ETH_SIGN: return new js_conflux_sdk_1.Message(message).hash; case message_1.MessageTypes.PERSONAL_SIGN: return new js_conflux_sdk_1.PersonalMessage(message).hash; // TODO: cip-23 depends on @findeth/abi which makes builds fail on android // import { getMessage } from 'cip-23'; // case MessageTypes.TYPE_DATA_V3: // case MessageTypes.TYPE_DATA_V4: // return keccak256(getMessage(JSON.parse(message))); default: throw new Error(`Invalid messageType: ${type}`); } } class Provider extends abc_1.BaseProvider { get conflux() { return this.clientSelector((i) => i instanceof conflux_1.Conflux); } internalPubkeyToAddress(pubkey) { const ethAddress = this.ethAddressToCfxAddress((0, keccak256_1.keccak256)(pubkey).slice(-40)); const networkID = parseInt(this.chainInfo.implOptions.chainId); return (0, conflux_address_js_1.encode)(ethAddress, networkID); } verifyAddress(address) { const isValid = (0, conflux_address_js_1.isValidCfxAddress)(address); return Promise.resolve({ normalizedAddress: isValid ? address.toLowerCase() : undefined, displayAddress: isValid ? address.toLowerCase() : undefined, isValid, }); } async pubkeyToAddress(verifier, encoding) { const uncompressPubKey = await verifier.getPubkey(false); return this.internalPubkeyToAddress(uncompressPubKey.slice(1)); } /** * transform the eth address to cfx format address * @param address the eth format address {string} * @returns the cfx format address {string} */ ethAddressToCfxAddress(address) { return `0x1${address.toLowerCase().slice(1)}`; } async buildUnsignedTx(unsignedTx) { const input = unsignedTx.inputs[0]; const output = unsignedTx.outputs[0]; const payload = unsignedTx.payload || {}; let nonce = unsignedTx.nonce; let feeLimit = unsignedTx.feeLimit; if (input && output) { const fromAddress = input.address; const tokenAddress = output.tokenAddress; let toAddress = output.address; let value = (0, bignumber_plus_1.toBigIntHex)(output.value); let data; if (tokenAddress) { toAddress = '0x' + (0, conflux_address_js_1.decode)(toAddress).hexAddress.toString('hex'); data = '0xa9059cbb' + abi_1.defaultAbiCoder .encode(['address', 'uint256'], [toAddress, value]) .slice(2); // method_selector(transfer) + byte32_pad(address) + byte32_pad(value) value = '0x0'; toAddress = tokenAddress; } else { data = payload.data; } if (typeof data === 'string' && data) { payload.data = data; } if (!feeLimit) { const estimatedGasLimit = await (await this.conflux).estimateGasLimit(fromAddress, toAddress, value, data); const estimatedGasLimitBN = (0, bignumber_plus_1.fromBigIntHex)(estimatedGasLimit); const multiplier = this.chainInfo.implOptions['contract_gaslimit_multiplier'] || 1.2; feeLimit = tokenAddress || (await (await this.conflux).isContract(toAddress)) ? estimatedGasLimitBN.multipliedBy(multiplier).integerValue() : estimatedGasLimitBN; } if (typeof nonce !== 'number' || nonce < 0) { const [addressInfo] = await (await this.conflux).getAddresses([fromAddress]); nonce = addressInfo === null || addressInfo === void 0 ? void 0 : addressInfo.nonce; } const [_, storageLimit] = await (await this.conflux).estimateGasAndCollateral(fromAddress, toAddress, value, data); const epochHeight = await (await this.conflux).getEpochNumber(); payload.storageLimit = (0, bignumber_plus_1.fromBigIntHex)(storageLimit); payload.epochHeight = epochHeight; } const feePricePerUnit = unsignedTx.feePricePerUnit || (await (await this.conflux).getFeePricePerUnit()).normal.price; feeLimit = feeLimit || new bignumber_js_1.default(21000); return Object.assign(unsignedTx, { inputs: input ? [input] : [], outputs: output ? [output] : [], nonce, feeLimit, feePricePerUnit, payload, }); } async signTransaction(unsignedTx, signers) { var _a; const fromAddress = (_a = unsignedTx.inputs[0]) === null || _a === void 0 ? void 0 : _a.address; (0, precondtion_1.check)(fromAddress && signers[fromAddress], 'Signer not found'); const params = this.buildCFXUnSignedTx(unsignedTx); const unSignedTx = new js_conflux_sdk_1.Transaction(params); const digest = (0, keccak256_1.keccak256)(unSignedTx.encode(false)); const [sig, recoveryParam] = await signers[fromAddress].sign(Buffer.from(digest.slice(2), 'hex')); const [r, s] = [sig.slice(0, 32), sig.slice(32)]; const SignedTx = new js_conflux_sdk_1.Transaction({ ...params, r: (0, bytes_1.hexZeroPad)('0x' + r.toString('hex'), 32), s: (0, bytes_1.hexZeroPad)('0x' + s.toString('hex'), 32), v: recoveryParam, }); const rawTx = SignedTx.serialize(); const txid = (0, keccak256_1.keccak256)(rawTx); return { txid, rawTx }; } buildCFXUnSignedTx(unsignedTx) { var _a; const output = unsignedTx.outputs[0]; const isERC20Transfer = !!output.tokenAddress; const toAddress = isERC20Transfer ? output.tokenAddress : output.address; const value = isERC20Transfer ? '0x0' : output.value; return { to: toAddress, value, gas: (0, precondtion_1.checkIsDefined)(unsignedTx.feeLimit), gasPrice: (0, precondtion_1.checkIsDefined)(unsignedTx.feePricePerUnit), storageLimit: unsignedTx.payload.storageLimit, epochHeight: unsignedTx.payload.epochHeight, nonce: (0, precondtion_1.checkIsDefined)(unsignedTx.nonce), data: ((_a = unsignedTx.payload) === null || _a === void 0 ? void 0 : _a.data) || '0x', chainId: parseInt((0, precondtion_1.checkIsDefined)(this.chainInfo.implOptions.chainId)), }; } async hardwareGetXpubs(paths, showOnDevice) { const resp = await this.wrapHardwareCall(() => js_sdk_1.default.confluxGetPublicKey({ bundle: paths.map((path) => ({ path, showOnTrezor: showOnDevice })), })); return resp.map((i) => ({ path: i.serializedPath, xpub: i.xpub, })); } async hardwareGetAddress(path, showOnDevice, addressToVerify) { const params = { path, showOnTrezor: showOnDevice, chain_id: Number((0, precondtion_1.checkIsDefined)(this.chainInfo.implOptions.chainId)), }; if (typeof addressToVerify === 'string') { Object.assign(params, { address: addressToVerify, }); } const { address } = await this.wrapHardwareCall(() => js_sdk_1.default.confluxGetAddress(params)); return address; } async hardwareSignTransaction(unsignedTx, signers) { const { inputs: [{ address: fromAddress }], } = unsignedTx; const signer = signers[fromAddress]; (0, precondtion_1.check)(signer, 'Signer not found'); const tx = this.buildCFXUnSignedTx(unsignedTx); const { r, s, v } = await this.wrapHardwareCall(() => js_sdk_1.default.confluxSignTransaction({ path: signer, transaction: { to: tx.to, value: tx.value, gasPrice: tx.gasPrice, gasLimit: tx.gasLimit, nonce: ethUtil.addHexPrefix( // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ethUtil.padToEven(tx.nonce.toString(16))), epochHeight: tx.epochHeight, storageLimit: tx.storageLimit, chainId: tx.chainId, data: tx.data, }, })); const SignedTx = new js_conflux_sdk_1.Transaction({ ...tx, r: ethUtil.addHexPrefix(r), s: ethUtil.addHexPrefix(s), v: Number(v), }); const rawTx = SignedTx.serialize(); const txid = (0, keccak256_1.keccak256)(rawTx); return { txid, rawTx }; } async hardwareSignMessage(message, signer) { const { type: messageType, message: strMessage } = message; switch (messageType) { case message_1.MessageTypes.PERSONAL_SIGN: { const { signature } = await this.wrapHardwareCall(() => js_sdk_1.default.confluxSignMessage({ path: signer, message: strMessage, })); return ethUtil.addHexPrefix(signature); } case message_1.MessageTypes.TYPE_DATA_V3: case message_1.MessageTypes.TYPE_DATA_V4: { const { signature } = await this.wrapHardwareCall(() => js_sdk_1.default.ConfluxSignMessageCIP23({ path: signer, data: JSON.parse(strMessage), })); return ethUtil.addHexPrefix(signature); } } throw new Error(`Not supported`); } async hardwareVerifyMessage(address, message, signature) { const { type: messageType, message: strMessage } = message; if (messageType === message_1.MessageTypes.PERSONAL_SIGN) { const { message: resp } = await this.wrapHardwareCall(() => js_sdk_1.default.confluxVerifyMessage({ address, message: strMessage, signature, })); return resp === 'Message verified'; } throw new Error('Not supported'); } async signMessage(message, signer, address) { return js_conflux_sdk_1.Message.sign('0x' + (await signer.getPrvkey()).toString('hex'), hashCfxMessage(message)); } async verifyMessage(address, message, signature) { const messageHash = hashCfxMessage(message); // Message.recover returns a string with 0x prefix. const publicKey = js_conflux_sdk_1.Message.recover(signature, messageHash).slice(2); return Promise.resolve(address === this.internalPubkeyToAddress(Buffer.from(publicKey, 'hex'))); } } exports.Provider = Provider; //# sourceMappingURL=provider.js.map