
Security News
/Research
Wallet-Draining npm Package Impersonates Nodemailer to Hijack Crypto Transactions
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
@protyze/web_pen_sdk
Advanced tools
This document is written to be used the web_pen_sdk for NeoSmartPen.
# web_pen_sdk setting
$ npm install web_pen_sdk
$ yarn add web_pen_sdk
scanPen, connectDevice, serviceBinding_16, serviceBinding_128, characteristicBinding, disconnect, dotCallback, handleDot, messageCallback, handleMessage, ncodeToScreen, ncodeToScreen_smartPlate, isSamePage
블루투스 펜 연결을 위해 디바이스를 스캔하는 로직입니다.
/** This function scans the device for bluetooth pen connection. */
scanPen = async () => { ... }
// Usage with react hook
const scanPen = () => {
PenHelper.scanPen();
};
<Button onClick={scanPen}></Button>
실제 블루투스 장비와의 연결을 시도합니다.
connectDevice = async (device: any) => { ... }
블루투스 service를 16bit/128bit UUID로 binding 합니다.
serviceBinding_16 = async (service: any, device: any) => { ... }
serviceBinding_128 = async (service: any, device: any) => { ... }
블루투스 펜 장비의 연결이 완료된 후 발생되는 펜 event를 처리하기 위해 PenController를 설정합니다.
연결된 펜의 정보, Dot 처리 등 모든 펜 event는 PenController를 통해 처리됩니다.
해당 penController는 PenHelper.pens[] 안에 저장됩니다.
characteristicBinding = (read: any, write: any, device: any) => { ... }
// PenHelper.ts
this.pens = [penController, penController, ...];
// penController 사용씬 2-1 참조
블루투스 장비 연결을 해제합니다.
disconnect = (penController: any) => { ... }
// Usage with react hook
const disconnectPen = () => {
PenHelper.disconnect(controller);
}
블루투스 펜의 이벤트를 처리합니다.
handleMessage = (controller: any, type: any, args: any) => { ... }
Type (Hex) | Title | Description | |
---|---|---|---|
1 (0x01) | PEN_AUTHORIZED | 펜 인증성공 | - |
2 (0x02) | PEN_PASSWORD_REQUEST | 비밀번호 요청 | - |
4 (0x04) | PEN_DISCONNECTED | 펜 연결해제 | - |
6 (0x06) | PEN_CONNECTION_SUCCESS | 펜 연결 성공 | - |
17 (0x11) | PEN_SETTING_INFO | 펜의 상태정보(배터리, 메모리 등) | 펜 충전시 배터리정보 -> 128 |
18 (0x12) | PEN_SETUP_SUCCESS | 펜 설정 변경 성공 | - |
19 (0x13) | PEN_SETUP_FAILURE | 펜 설정 변경 실패 | - |
26 (0x1a) | PEN_USING_NOTE_SET_RESULT | 실시간 필기 데이터 요청 결과 | - |
82 (0x52) | PASSWORD_SETUP_SUCCESS | 패스워드 설정 성공 | - |
83 (0x53) | PASSWORD_SETUP_FAILURE | 패스워드 설정 실패 | - |
84 (0x54) | PEN_ILLEGAL_PASSWORD_0000 | 신규 패스워드 0000 제한 | - |
99 (0x63) | EVENT_LOW_BATTERY | 배터리 잔량 부족시 이벤트 | - |
100 (0x64) | EVENT_POWER_OFF | 전원 OFF 이벤트 | - |
34 (0x22) | PEN_FW_UPGRADE_STATUS | 펜 펌웨어 업그레이드 상태 | - |
35 (0x23) | PEN_FW_UPGRADE_SUCCESS | 펜 펌웨어 업그레이드 성공 | - |
36 (0x24) | PEN_FW_UPGRADE_FAILURE | 펜 펌웨어 업드레이드 실패 | 1=동일버전/2=공간부족/3=실패/4=압축지원X |
37 (0x25) | PEN_FW_UPGRADE_SUSPEND | 펜 펌웨어 업그레이드 중단 | - |
48 (0x30) | OFFLINE_DATA_NOTE_LIST | 오프라인 데이터 노트 리스트 | - |
49 (0x31) | OFFLINE_DATA_PAGE_LIST | 오프라인 데이터 페이지 리스트 | - |
50 (0x32) | OFFLINE_DATA_SEND_START | 오프라인 데이터 보내기 시작 | - |
51 (0x33) | OFFLINE_DATA_SEND_STATUS | 오프라인 데이터 보내는 상태 | - |
52 (0x34) | OFFLINE_DATA_SEND_SUCCESS | 오프라인 데이터 보내기 성공 | - |
53 (0x35) | OFFLINE_DATA_SEND_FAILURE | 오프라인 데이터 보내기 실패 | - |
165 (0xa5) | OFFLINE_DATA_DELETE_RESPONSE | 오프라인 데이터 삭제 상태 | - |
84 (0x54) | PEN_CONNECTION_FAILURE_BTDUPLICATE | 중복되는 블루투스 펜 연결 시도시 실패 | - |
193 (0xc1) | PEN_PROFILE | 펜의 프로필 | - |
115 (0x73) | RES_PDS | 펜 PDS | - |
104 (0x68) | EVENT_DOT_ERROR | 펜 Dot 이벤트 에러 | - |
105 (0x69) | EVENT_DOT_PUI | 펜 Dot PUI 정보 | - |
244 (0xf4) | RES_LOG_INFO | 펜 로그 정보 | - |
245 (0xf5) | RES_LOG_DATA | 펜 로그 데이터 | - |
// Usage with react hook
const [controller, setController] = useState();
const [penVersionInfo, setPenVersionInfo] = useState();
const [battery, setBattery] = useState();
useEffect(() => {
PenHelper.messageCallback = async (mac, type, args) => {
messageProcess(mac, type, args);
}
});
const messageProcess = (mac, type, args) => {
switch(type) {
case PenMessageType.PEN_SETTING_INFO:
const _controller = PenHelper.pens.filter((c) => c.info.MacAddress === mac)[0];
setController(_controller); // 해당 펜의 controller를 등록해준다.
setBattery(args.Battery); // 배터리 상태정보를 저장 -> 충전중일 때 128로 표시
...
case PenMessageType.PEN_DISCONNECTED: // 펜 연결해제시 모든 상태값 초기화
setController(null);
setPenInfo(null);
setBattery(null);
case PenMessageType.PEN_PASSWORD_REQUEST: ... // 패스워드 요청시 처리
onPasswordRequired(args);
case PenMessageType.PEN_SETUP_SUCCESS: // 팬 연결 성공시 처리
if (controller) {
setPenVersionInfo(controller.info);
}
...
}
}
...
const onPasswordRequired = (args: any) => {
const password = input();
...
if (args.RetryCount >= 10) {
alert('펜의 모든정보가 초기화 됩니다.');
}
...
controller.InputPassword(password); // 등록된 펜 controller를 사용하여 비밀번호를 전달한다.
}
...
펜에서 넘어온 dot 데이터는 penController에 등록된 callback 함수인 handleDot을 통해 처리됩니다.
handleDot = (controller: any, args: any) => { ... }
일반적인 ncode dot 좌표값을 view에 보여지게 하기 위하여 view size에 맞춰 변환시키는 로직입니다.
/**
* This function is to convert the general ncode dot coordinate values according to the view size in order to be shown in the view.
*
* @param {Dot} dot
* @param {View} view
* @param {PaperSize} paperSize
* @returns {ScreenDot}
*/
ncodeToScreen = (dot: Dot, view: View, paperSize: PaperSize) => {
...
}
SmartPlate의 ncode dot 좌표값을 view에 보여지게 하기 위하여 view size에 맞춰 변환시키는 로직입니다.
/**
* This function is to convert the SmartPlate ncode dot coordinate values according to the view size in order to be shown in the view.
*
* @param {Dot} dot
* @param {View} view
* @param {number} angle - possible angle value [0', 90', 180', 270']
* @param {PaperSize} paperSize
* @returns {ScreenDot}
*/
ncodeToScreen_smartPlate = (dot: Dot, view: View, angle: number, paperSize: PaperSize) => {
...
}
// Usage with react hook
useEffect(() => {
PenHelper.dotCallback = async (mac, dot) => {
strokeProcess(dot);
}
});
const strokeProcess = (dot: Dot) => {
...
const view = { width: canvasFb.width, height: canvasFb.height };
let screenDot: ScreenDot;
if (PenHelper.isSamePage(dot.pageInfo, PlateNcode_3)) { // SmartPlate
screenDot = PenHelper.ncodeToScreen_smartPlate(dot, view, angle, paperSize);
} else { // Default
screenDot = PenHelper.ncodeToScreen(dot, view, paperSize);
}
...
}
서로 다른 ncode 페이지 정보(SOBP)를 바탕으로 같은 페이지인지 구별하기 위한 로직입니다.
SOBP는 페이지를 구별하기 위한 정보로서, Section/Owner/Book/Page의 줄임말입니다.
/**
* This function is to distinguish whether it is the same page based on different ncode page information (SOBP).
*
* @param {PageInfo} page1
* @param {PageInfo} page2
* @returns {boolean}
*/
isSamePage = (page1: PageInfo, page2: PageInfo) => {
...
}
extractMarginInfo, getNoteImage
펜으로부터 받은 페이지 정보(SOBP)를 바탕으로 nproj로 부터 해당 ncode 페이지의 margin info를 추출하는 로직입니다.
/**
* This function is to extract the margin info of the ncode page from nproj based on pageInfo.
*
* @param {PageInfo} pageInfo
* @returns {PaperSize}
*/
const extractMarginInfo = async (pageInfo: PageInfo) => {
...
}
펜으로부터 받은 페이지 정보(SOBP)를 바탕으로 노트의 이미지를 받아오기 위한 로직입니다.
/**
* This function is to get the note image based on pageInfo.
*
* @param {PageInfo} pageInfo
* @param {React.dispatch} setImageBlobUrl
* @returns {boolean} - success -> setImageBlobUrl(imageBlobUrl)
*/
const getNoteImage = async (pageInfo: PageInfo, setImageBlobUrl: any) => {
...
}
// Usage with react hook
const [imageBlobUrl, setImageBlobUrl] = useState<string>();
const [paperSize, setPaperSize] = useState<PaperSize>();
useEffect(() => {
async function getNoteImageUsingAPI(pageInfo) {
await NoteServer.getNoteImage(pageInfo, setImageBlobUrl);
const paperSize: PaperSize = await NoteServer.extractMarginInfo(pageInfo);
setPaperSize(paperSize);
}
if (pageInfo) {
getNoteImageUsingAPI(pageInfo);
}
}, [pageInfo]);
RequestVersionInfo, SetPassword, InputPassword, RequestPenStatus, SetRtcTime, SetAutoPowerOffTime, SetPenCapPowerOnOffEnable, SetAutoPowerOnEnable, SetBeepSoundEnable, SetHoverEnable, SetOfflineDataEnable, SetColor, RequestAvailableNotes, RequestOfflineNoteList, RequestOfflinePageList, RequestOfflineData, RequestOfflineDelete, RequestFirmwareInstallation, RequestFirmwareUpload, RequestProfileInfo.., RequestProfileReadValue..
Methods | Parameters | Description |
---|---|---|
RequestVersionInfo | 펜의 현재 버전을 요청 | |
SetPassword | oldone: string, newone: string | 펜에 설정된 비밀번호를 변경 요청 |
InputPassword | password: string | 펜에 비밀번호를 전송 |
RequestPenStatus | 펜의 각종 설정 확인을 요청 | |
SetRtcTime | 펜에 설정된 시각을 현재 시각으로 변경 요청 | |
SetAutoPowerOffTime | minute: number | 펜에 설정된 자동종료 시간을 변경 요청 ( 최대 3600 분 ) |
SetPenCapPowerOnOffEnable | enable: boolean | 펜에 설정된 펜 뚜껑을 이용한 전원 ON/OFF 기능 변경 요청 |
SetAutoPowerOnEnable | enable: boolean | 펜에 설정된 펜 뚜껑 혹은 필기를 이용한 전원 ON 기능 변경 요청 |
SetBeepSoundEnable | enable: boolean | 펜에 설정된 비프음 기능 변경 요청 |
SetHoverEnable | enable: boolean | 펜에 설정된 호버 기능 변경 요청 ( 호버 : 필기 위치 가늠을 위한 시각적 Dot 표시 기능) |
SetOfflineDataEnable | enable: boolean | 펜에 설정된 오프라인 필기 데이터 저장 기능 변경 요청 |
SetColor | color: number | 펜에 설정된 LED 색상 변경 요청 ( argb ) |
RequestAvailableNotes | sections: number[ ], owners: number[ ], notes: number[ ] | null | 펜에 실시간 필기 데이터에 대한 전송을 요청 ( notes 가 null 일 경우 노트 구분 없이 요청 ) |
RequestOfflineNoteList | section: number, owner: number | 펜에 저장된 오프라인 필기 데이터의 페이지 정보(book)를 요청 ( SO 가 0 일 경우 모든 note 리스트 반환 ) |
RequestOfflinePageList | section: number, owner: number, note: number | 펜에 저장된 오프라인 필기 데이터의 페이지 정보(page)를 요청 ( SOB 가 일치하는 한 노트의 page ) |
RequestOfflineData | section: number, owner: number, note: number, deleteOnFinished: boolean, pages: number[ ] | 펜에 저장된 오프라인 필기 데이터를 요청 ( P 가 빈 배열일 경우 노트 내 모든 page 요청 ) ( deleteOnFinished 가 true일 경우 전송 완료된 데이터 삭제 ) |
RequestOfflineDelete | section: number, owner: number, notes: number[ ] | 펜에 저장된 오프라인 필기 데이터에 대한 삭제를 요청 |
RequestFirmwareInstallation | file: file, version: string, isCompressed: boolean | 펜에 설치된 펌웨어를 업그레이드하기 위한 질의 |
RequestFirmwareUpload | offset: number, data: Uint8Array, status: number | 펜에 펌웨어 데이터를 업로드 |
RequestProfileCreate | name: string, password: string | 펜에 프로파일 생성을 요청 |
ReqeustProfileDelete | name: string, password: string | 펜에 설정된 프로파일 제거 요청 |
RequestProfileInfo | name: string | 펜에 설정된 프로파일 정보 요청 |
RequestProfileWriteValue | name: string, passsword: string, data: { [key: string]: any } | 펜에 설정된 프로파일 내 데이터 작성 요청 |
RequestProfileReadValue | name: string, keys: string[ ] | 펜에 설정된 프로파일 내 데이터 정보 요청 |
RequestProfileDeleteValue | name: string, password: string, keys: string [ ] | 펜에 설정된 프로파일 내 데이터 제거 요청 |
import { PenHelper, NoteServer, PenMessageType } from 'web_pen_sdk';
/** Connect SmartPen to Web service */
PenHelper.scanPen();
useEffect(() => {
PenHelper.messageCallback = async (mac, type, args) => {
messageProcess(mac, type, args)
}
});
const messageProcess = (mac, type, args) => {
switch(type) {
case PenMessageType.x:
...
}
}
/** Data Parsing from SmartPen */
PenHelper.dotCallback = (mac, dot) => {
strokeProcess(dot);
}
const strokeProcess = (dot: Dot) => {
...
}
/** Use NoteServer.extractMarginInfo() function to get size information of the ncode paper. */
const [paperSize, setPaperSize] = useState<PaperSize>();
const paperSize: PaperSize = await NoteServer.extractMarginInfo(pageInfo);
/** Use NoteServer.getNoteImage() function to get image url of the note. */
const [imageBlobUrl, setImageBlobUrl] = useState<string>();
await NoteServer.getNoteImage(pageInfo, setImageBlobUrl);
/**
* Draw on Canvas with SmartPen
* Coordinate Transformation with ncode_dot based on view_size, ncode_size
*/
const strokeProcess = (dot: Dot) => {
const view = { width: canvasFb.width, height: canvasFb.height };
// case Default:
const screenDot = PenHelper.ncodeToScreen(dot, view, paperSize);
// case SmartPlate:
const screenDot = PenHelper.ncodeToScreen_smartPlate(dot, view, angle, paperSize)
/** Create path data using screenDot */
const path = new Path(screenDot.x, screenDot.y);
}
Google Docs
FAQs
Neosmartpen typescript library
The npm package @protyze/web_pen_sdk receives a total of 6 weekly downloads. As such, @protyze/web_pen_sdk popularity was classified as not popular.
We found that @protyze/web_pen_sdk demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
/Research
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.
Security News
/Research
Malicious Nx npm versions stole secrets and wallet info using AI CLI tools; Socket’s AI scanner detected the supply chain attack and flagged the malware.