ens-normalize.js
0-의존성 Ethereum Name Service (ENS) 이름 정규화기.npm i @adraffy/ens-normalize ✓
- 🏛️ ENSIP-15: ENS 이름 정규화 표준을 준수
- 유니코드:
17.0.0• CLDR:47 - 기타 구현체:
- 파이썬 — namehash/ens-normalize-python
- 러스트 — sevenzing/ens-normalize-rs
- 직(Zig) — evmts/z-ens-normalize
- C# — adraffy/ENSNormalize.cs
- 자바 — adraffy/ENSNormalize.java
- 스위프트 – adraffy/ENSNormalize.swift
- 고 — adraffy/go-ens-normalize
- 스위프트 – adraffy/ENSNormalize.swift
- 이전 구현체:
- 자바스크립트 — ensdomains/eth-ens-namehash
- ENSIP-1 분해 보고서
- ✅️ 100% ENSIP-15 검증 테스트 통과
- ✅️ 100% 유니코드 정규화 테스트 통과
- 압축 파일 크기:
29KB—String.normalize()를 사용한 nf-native.js 기반 네이티브 NFC ⚠️38KB기본 — nf.js 기반 커스텀 NFC
44KB 모두 포함!* — 커스텀 NFC + 서브 라이브러리: parts.js, utils.js
- 포함된 앱:
- 리졸버 데모 ⭐
- 지원하는 이모지
- 문자 뷰어
- 혼란스러운 설명기
- 관련 프로젝트:
- 최근 .eth 등록 • 갱신 • 만료
- 라벨 데이터베이스 • Labelhash⁻¹ • 무차별 대입
- 이모지 빈도 탐색기
- adraffy/punycode.js • Punycode 인코더
- adraffy/keccak.js • Keccak 해시
- adraffy/emoji.js • 이모지 파서
- 더 많은 링크는 리졸버 데모 하단에 있음
import {ens_normalize} from '@adraffy/ens-normalize'; // or require()
// browser: https://cdn.jsdelivr.net/npm/@adraffy/ens-normalize@latest/dist/index.min.mjs (or .cjs)// ALL errors thrown by this library are safe to print
// - characters are shown as {HEX} if should_escape()
// - potentially different bidi directions inside "quotes"
// - 200E is used near "quotes" to prevent spillover
// - an "error type" can be extracted by slicing up to the first (:)
// - labels are middle-truncated with ellipsis (…) at 63 cps
// string -> string
// throws on invalid names
// output ready for namehash
let normalized = ens_normalize('RaFFY🚴♂️.eTh');
// => "raffy🚴♂.eth"
// note: does not enforce .eth registrar 3-character minimum
이모지로 완전히 한정된 형식 이름:
// works like ens_normalize()
// output ready for display
let pretty = ens_beautify('1⃣2⃣.eth');
// => "1️⃣2️⃣.eth"// note: normalization is unchanged:
// ens_normalize(ens_beautify(x)) == ens_normalize(x)
부분 문자열 검색을 위한 이름 조각 정규화:
// these fragments fail ens_normalize()
// but will normalize fine as fragments
let frag1 = ens_normalize_fragment('AB--'); // expected error: label ext
let frag2 = ens_normalize_fragment('\u{303}'); // expected error: leading cm
let frag3 = ens_normalize_fragment('οо'); // expected error: mixture
입력 기반 토큰화:// string -> Token[]
// never throws
let tokens = ens_tokenize('_R💩\u{FE0F}a\u{FE0F}\u{304}\u{AD}./');
// [
// { type: 'valid', cps: [ 95 ] }, // valid (as-is)
// {
// type: 'mapped',
// cp: 82, // input
// cps: [ 114 ] // output
// },
// {
// type: 'emoji',
// input: Emoji(2) [ 128169, 65039 ], // input
// emoji: [ 128169, 65039 ], // fully-qualified
// cps: Emoji(1) [ 128169 ] // output (normalized)
// },
// {
// type: 'nfc',
// input: [ 97, 772 ], // input (before nfc)
// cps: [ 257 ], // output (after nfc)
// tokens0: [ // tokens (before nfc)
// { type: 'valid', cps: [ 97 ] },
// { type: 'ignored', cp: 65039 },
// { type: 'valid', cps: [ 772 ] }
// ],
// tokens: [ // tokens (after nfc)
// { type: 'valid', cps: [ 257 ] }
// ]
// },
// { type: 'ignored', cp: 173 },
// { type: 'stop', cp: 46 },
// { type: 'disallowed', cp: 47 }
// ]// note: if name is normalizable, then:
// ens_normalize(ens_tokenize(name).map(token => {
// convert valid/mapped/nfc/stop to string
// }).join('')) == ens_normalize(name)
출력 기반 토크나이제이션:// string -> Label[]
// never throws
let labels = ens_split('💩Raffy.eth_');
// [
// {
// input: [ 128169, 82, 97, 102, 102, 121 ],
// offset: 0, // index of codepoint, not substring index!
// // (corresponding length can be inferred from input)
// tokens: [
// Emoji(2) [ 128169, 65039 ], // emoji
// [ 114, 97, 102, 102, 121 ] // nfc-text
// ],
// output: [ 128169, 114, 97, 102, 102, 121 ],
// emoji: true,
// type: 'Latin'
// },
// {
// input: [ 101, 116, 104, 95 ],
// offset: 7,
// tokens: [ [ 101, 116, 104, 95 ] ],
// output: [ 101, 116, 104, 95 ],
// error: Error('underscore allowed only at start')
// }
// ]지원되는 이모지 코드포인트의 정렬된 배열(보기 좋게) 생성:
// () -> number[][]
let emojis = ens_emoji();
// [
// [ 2764 ],
// [ 128169, 65039 ],
// [ 128105, 127997, 8205, 9877, 65039 ],
// ...
// ]문자가 직접 출력되지 않아야 하는지 확인하십시오:
// number -> bool
should_escape(0x202E); // eg. RIGHT-TO-LEFT OVERRIDE => true문자가 결합 부호인지 확인:
// number -> bool
is_combining_mark(0x20E3); // eg. COMBINING ENCLOSING KEYCAP => true코드포인트를 출력 안전 문자열로 포맷:
// number[] -> string
safe_str_from_cps([0x300, 0, 32, 97]); // "◌̀{00} a"
safe_str_from_cps(Array(100).fill(97), 4); // "aa…aa" => middle-truncated
빌드
- 이 저장소를
git clone한 후,npm install실행 - /derive/ 내 지침에 따라 데이터 파일 생성
npm run derive- spec.json
- nf.json
- nf-tests.json
npm run make— /derive/output/에서 데이터 파일 압축- include-ens.js
- include-nf.js
- include-versions.js
- /validate/ 내 지침에 따라 검증 테스트 생성
npm run validate- tests.json
npm run test— 검증 테스트 수행npm run build— /dist/ 생성npm run rebuild— 위 명령 모두 실행npm run order— 최적 그룹 순서 생성 후 다시 빌드
보안
- 빌드 후 include-versions.js와 비교
spec_hash— spec.json 바이트의 SHA-256ens_hash_base64— include-ens.js base64 리터럴의 SHA-256nf_hash_base64— include-nf.js base64 리터럴의 SHA-256