UNPKG

dotbit-sdk-allin

Version:

A complete .bit SDK and utilities in TypeScript

102 lines (86 loc) 3.63 kB
import { MessageTypes, SignTypedDataVersion, TypedDataUtils, TypedMessage } from '@metamask/eth-sig-util' import { JsonRpcSigner } from '@ethersproject/providers' import { Wallet } from 'ethers' import { AlgorithmId, CoinType, EvmChainId2CoinType } from '../const' import { TxsSignedOrUnSigned } from '../fetchers/SubAccountAPI' import { TxsWithMMJsonSignedOrUnSigned } from '../fetchers/RegisterAPI.type' import { BitErrorCode, DotbitError } from '../errors/DotbitError' import { remove0x } from '../tools/common' function isMMJson (txs: TxsSignedOrUnSigned | TxsWithMMJsonSignedOrUnSigned): txs is TxsWithMMJsonSignedOrUnSigned { return 'mm_json' in txs } /** * get mmJson hash and chainId hex * @param typedData * @param chainId */ export function mmJsonHashAndChainIdHex (typedData: TypedMessage<any>, chainId: number): string { const mmHash = TypedDataUtils.eip712Hash(typedData, SignTypedDataVersion.V4).toString('hex') const chainIdHex = chainId.toString(16).padStart(16, '0') return mmHash + chainIdHex } export interface SendTransactionParam { to: string, value: string, data: string, } export abstract class BitSigner { signer: JsonRpcSigner| Wallet abstract signTypedData (data: TypedMessage<MessageTypes>): Promise<string> abstract sendTransaction (sendTransactionParam: SendTransactionParam): Promise<string> signPersonal (data: string| Buffer): Promise<string> { return this.signer.signMessage(data) } getAddress () { return this.signer.getAddress() } getChainId () { return this.signer.getChainId() } async getCoinType (): Promise<CoinType> { const chainId = await this.getChainId() const coinType = EvmChainId2CoinType[chainId] if (!coinType) { throw new DotbitError(`Unsupported EVM chainId: ${chainId}`, BitErrorCode.UnsupportedEVMChainId) } return coinType } async signData (data: string | Buffer | object, isEIP712?: boolean): Promise<string> { if (isEIP712) { return await this.signTypedData(data as TypedMessage<MessageTypes>) } else { return await this.signPersonal(data as string | Buffer) } } // todo-open: TxsSignedOrUnSigned and TxsWithMMJsonSignedOrUnSigned is pretty much the same, while they are from different api. We need to unify them in backend. async signTxList (txs: TxsSignedOrUnSigned): Promise<TxsSignedOrUnSigned> async signTxList (txs: TxsWithMMJsonSignedOrUnSigned): Promise<TxsWithMMJsonSignedOrUnSigned> async signTxList (txs: TxsSignedOrUnSigned | TxsWithMMJsonSignedOrUnSigned): Promise<TxsSignedOrUnSigned | TxsWithMMJsonSignedOrUnSigned> { if (isMMJson(txs)) { for (const signItem of txs.sign_list) { if (signItem.sign_msg) { if (signItem.sign_type === AlgorithmId.eip712) { const mmJson = JSON.parse(JSON.stringify(txs.mm_json)) mmJson.message.digest = signItem.sign_msg const signDataRes = await this.signTypedData(mmJson) signItem.sign_msg = signDataRes + mmJsonHashAndChainIdHex(mmJson, mmJson.domain.chainId) } else { signItem.sign_msg = await this.signData(Buffer.from(remove0x(signItem.sign_msg), 'hex')) } } } } else { for (const list of txs.list) { for (const signItem of list.sign_list) { if (signItem.sign_msg) { signItem.sign_msg = await this.signData(Buffer.from(remove0x(signItem.sign_msg), 'hex')) } } } } return txs } }