@eternl/hub-wallet-sdk

中文文档
0.55.0发布于 2026/11/10BUSL-1.1TypeScriptESM + CJS近 30 天下载 2487

Eternl Hub SDK用于钱包开发者.

中文使用文档
文档目录27 节
  1. 安装
  2. 运行时间要求
  3. 限制——模块级单子状态
  4. 配置
  5. 1. 初始化SDK
  6. 2. 所需NATS配置 - getNatsUrl + 键 getAuthenticator
  7. 快速启动
  8. API-钱包连接会议
  9. 选项( E) WalletConnectorSessionOptions (中文(简体) )
  10. 返回的 API ( WalletConnectorSessionApi (中文(简体) )
  11. 远程签名( 请求方)
  12. 存在信标和原始流存在
  13. 低级可堆肥
  14. 使用 Nats 客户端
  15. 使用复制
  16. 重放保护
  17. 使用会话密钥缓存
  18. 使用MessageAuth 数据
  19. 使用 Nats 校正
  20. 存储
  21. 公用事业
  22. 加农化(RFC 8785)
  23. 安全身份证
  24. 协议常数
  25. 协议类型和权限
  26. 安保模式(摘要)
  27. 许可证

@eternl/hub-wallet-sdk (英语)

一个基于可堆肥的SDK,供钱包开发者与Eternl Hub集成. 它为安全设备/dApp配对,端到端加密消息,存在,以及NATS WebSocket传输上的远程签名提供了钱包侧构件.

主要的高级切入点是 createWalletConnectorSession ——由它组成对称配对协议 @eternl/hub-core 并添加钱包作用逻辑(对应 dApp) apiCalls,账户切换,存在). 低级堆肥(useNatsClient, (中文(简体) ), useEncryption, (中文(简体) ), useReplayProtection,.)也为高级或自定义集成出口.

状态 : bUSL-1.1项下的源数据(见 许可证) (中文(简体) ). API正稳定在1.0发布 0.x,小版本可能包含断开的更改——检查 变化 升级前.

安装

npm install @eternl/hub-wallet-sdk
# or
pnpm add @eternl/hub-wallet-sdk

这取决于 @eternl/hub-core 和模块 @nats-io/*@3.x 客户(@nats-io/nats-core, (中文(简体) ), @nats-io/jetstream, (中文(简体) ), @nats-io/kv)作为依赖性自动安装.

运行时间要求

SDK需要安全的WebCrypto环境(现代浏览器或Node.js 18+). initHub() 电话 assertCryptoCapabilities() 并投掷,如果 crypto.subtle 编号 : crypto.getRandomValues 无法使用。 没有 Math.random() 在SDK的任何地方都掉头.

你可以自己探测能力:

import { checkCryptoCapabilities } from '@eternl/hub-wallet-sdk'

const caps = checkCryptoCapabilities()
// {
//   hasSubtleCrypto: boolean
//   hasRandomValues: boolean
//   hasRandomUUID:   boolean
//   isSecure:        boolean   // hasSubtleCrypto && hasRandomValues
// }
if (!caps.isSecure) {
  throw new Error('WebCrypto unavailable — SDK cannot run here')
}

限制——模块级单子状态

在设计您的整合之前先读一下.

几个核心模块 整个进程单子状态,而不是逐个状态:

  • useNatsClient ——一个NATS连接,一组回调,每个过程一个订阅地图. 通话 useNatsClient() 反复返回到 不变 基础连接. configure() 覆盖先前配置的提供者/召回 。 每个过程只有一个连接.
  • useEncryption —— 说 getCurrentKeyPair() 编号 : getCurrentSessionKey() 跟踪单个“当前”密钥对 / 会话密钥. generateKeyPair() 财务报告和审定财务报表 deriveSessionKeyHKDF() 覆盖他们.
  • signingTransport —— 说 configureSigningTransport(...) 设置一个全局配置, 由所有签名可混凝土消耗 .
  • getWalletPresenceBeacon() ——返回全过程的单通信标(因此所有会话都共享一个生命周期-发送器订阅).
  • useReplayProtection 编号 : useSessionKeyCache — 模块级缓存按键 pairId 编号 : deviceId。 。 。 .

实际后果: SDK 设计用于 每个 JS 上下文一个钱包客户端 (一个浏览器标签/一个节点进程). 没错 没有 安全运行两个独立,不同配置的钱包客户端在同一过程中. 需要隔离的测试应当通过导出测试帮助器(例如. __resetWalletPresenceBeaconForTests, (中文(简体) ), clearAllReplayCaches, (中文(简体) ), clearAllCachedKeys)或以不同的工人流程运行.

createWalletConnectorSession 本身返回独立的每平方对象,但它构成单通NATS传输和(默认情况下)下单通存在信标.

配置

1. 初始化SDK

import { initHub, isInitialized, getConfig } from '@eternl/hub-wallet-sdk'

initHub({ network: 'mainnet' })

// With options:
initHub({
  network: 'preprod',                              // 'mainnet' | 'preprod' | 'preview'
  hubUrl: 'wss://custom-hub.example.com/nats',     // default: wss://hub.de-5.eternl.art/nats
  storage: myStorage,                              // optional HubStorage adapter
  storagePrefix: 'my-wallet',                      // optional localStorage key prefix
  constants: { CONNECTION_TIMEOUT_MS: 20_000 },    // optional protocol-constant overrides
})

if (isInitialized()) {
  console.log('network:', getConfig().network)
}

2. 所需NATS配置 - getNatsUrl + 键 getAuthenticator

useNatsClient 已经 没有 从 initHub您必须拨打 configure() 至少有一个 getNatsUrl 连接前提供方 。 生产经纪人以违约方式进行交易,所以你还必须提供 getAuthenticator 那个薄荷糖 a 每笔捐款。 。 。 .

import { useNatsClient } from '@eternl/hub-wallet-sdk'
import { jwtAuthenticator } from '@nats-io/nats-core'

const nats = useNatsClient()

nats.configure({
  // Required. Returns the broker WebSocket URL.
  getNatsUrl: () => 'wss://hub.de-5.eternl.art/nats',

  // Per-pairing JWT model (R1.5 / C1.e).
  // Called immediately before EVERY connect attempt — including reconnects —
  // so you can mint a fresh per-pairing CLIENTS user JWT (e.g. POST /nats/token
  // on be-hub) each time. Returning `undefined` produces an anonymous
  // connection, which only works against local-dev / pre-R1.2 brokers.
  //
  // YOU are responsible for refresh-before-expiry: when the JWT nears `exp`,
  // call `disconnect()` then `connect()` to swap in a fresh token. The SDK
  // re-invokes this provider on the new connect.
  getAuthenticator: async () => {
    const { jwt, seed } = await mintPerPairingToken()  // your call to be-hub
    return jwtAuthenticator(jwt, new TextEncoder().encode(seed))
  },

  // Optional lifecycle / error callbacks:
  onConnected: () => console.log('connected'),
  onDisconnected: () => console.log('disconnected'),
  onError: (msg: string) => console.error('nats error:', msg),

  // Broker rejected the whole connection (AUTHORIZATION_VIOLATION). The SDK
  // does NOT auto-retry — clear your cached JWT, then either mint a fresh one
  // and call retry(), or surface a re-pair prompt.
  onPairRevoked: () => clearCachedJwtAndPromptRepair(),

  // Broker rejected a publish/subscribe (PERMISSIONS_VIOLATION). The
  // connection stays up; this fires per-subject for ACL denials.
  onPermissionsViolation: (subject?: string) => console.warn('ACL denied:', subject),
})

await nats.connect()

快速启动

最小端到端流:连接,确认连接是活的,然后运行钱包连接器会话进行对接.

import {
  initHub,
  useNatsClient,
  configureSigningTransport,
  createWalletConnectorSession,
  type ApiCallResult,
} from '@eternl/hub-wallet-sdk'

// 1. Init
initHub({ network: 'mainnet' })

// 2. Configure + connect transport
const nats = useNatsClient()
nats.configure({
  getNatsUrl: () => 'wss://hub.de-5.eternl.art/nats',
  getAuthenticator: async () => myJwtAuthenticator(),  // see "Required NATS configuration"
})
await nats.connect()

// connectionStatus() is a getter, not getConnectionStatus()
if (nats.connectionStatus() !== 'connected') {
  throw new Error(`NATS not connected: ${nats.connectionStatus()}`)
}

// 3. Run a wallet connector session for an established pairing.
//    `encryption` and `transport` here implement hub-core's SessionEncryptionApi
//    and Transport — typically built from the pairing's derived session key and
//    the NATS client. See "WalletConnectorSession" below.
const session = createWalletConnectorSession({
  pairId,                       // string — the established pairing id
  encryption,                   // SessionEncryptionApi (from @eternl/hub-core)
  transport,                    // Transport (from @eternl/hub-core)
  grantedPermissions,           // Permission[]
  walletName: 'My Wallet',
  apiCallHandler: async ({ method, args, accountId }): Promise<ApiCallResult> => {
    // Invoke the underlying CIP-30 method and return its result.
    const result = await myWallet.invoke(method, args, accountId)
    return { success: true, result }
  },
})

session.on('apiCallReceived', ({ method }) => console.log('dApp called', method))

API-钱包连接会议

createWalletConnectorSession(options) 在一个对齐上构建一个钱包作用会话 。 它拥有入境权 apiCall 调度、账户交换处理、访问/同意状态和存在。 导出 WalletConnectorSession 类是薄薄的包装器,可以返回工厂的结果.

选项( E)WalletConnectorSessionOptions(中文(简体) )

interface WalletConnectorSessionOptions {
  pairId: string
  encryption: SessionEncryptionApi          // from @eternl/hub-core
  transport: Transport                       // from @eternl/hub-core
  grantedPermissions: Permission[]           // enforced for signing-method ACLs

  requireConsent?: boolean                   // default false → auto-grants all categories on start
  autoEstablishAllowed?: boolean             // default true
  walletName?: string

  apiCallHandler: ApiCallHandler             // REQUIRED
  accountSwitchHandler?: AccountSwitchHandler

  onPeerDisconnect?: (reason: string) => void
  onPeerPairingRemoved?: (reason: string) => void
  onError?: (err: Error) => void

  // Opt-in raw-stream presence (Option C):
  presenceC?: { deviceId: string; tabId: string; getNc: () => NatsConnection | null }
  presenceBeacon?: WalletPresenceBeaconApi   // override singleton (tests only)
}

type ApiCallResult =
  | { success: true; result: unknown }
  | { success: false; errorCode: string; errorMessage: string }

type ApiCallHandler = (params: {
  method: string
  args: unknown[]
  accountId: string
  requestId: string
}) => Promise<ApiCallResult>

type AccountSwitchHandler = (params: { accountId: string }) => Promise<boolean>

返回的 API (WalletConnectorSessionApi(中文(简体) )

const session = createWalletConnectorSession(options)

session.pairId                  // string
session.accessGranted           // boolean
session.grantedCategories       // CIP30Category[] (copy)
session.grantedPermissions      // readonly Permission[]

// Consent (only needed when requireConsent: true; otherwise auto-granted on start)
await session.grantAccess(['core', 'governance', 'extension'], /* autoEstablishAllowed */ true)
await session.denyAccess('User declined')

// Push account changes to the dApp
await session.notifyAccountsChanged(accounts, activeAccountId, 'updated')

// Presence
await session.requestPresenceCheck(/* timeoutMs? */ 5000)        // Promise<boolean>
await session.requestPresenceCSnapshot()                         // Option C only; else resolves null
await session.notifyOnline()
await session.notifyOffline('tab hidden')

// Teardown
await session.disconnect('Wallet disconnected')   // sends DISCONNECT, then disposes
await session.remove('Pairing removed')           // sends PAIRING_REMOVED, then disposes
session.dispose()                                 // local cleanup, no message

// Events (returns an unsubscribe fn)
const off = session.on('apiCallReceived', ({ method, accountId, requestId }) => { /* … */ })
session.on('accountSwitchRequested', ({ accountId }) => { /* … */ })
session.on('pingReceived', ({ timestamp }) => { /* … */ })
session.on('heartbeatReceived', ({ timestamp }) => { /* … */ })
session.on('peerPresence', ({ status, reason, sentAt }) => { /* … */ })
session.on('peerPresenceC', (event) => { /* … */ })          // Option C only
session.on('accessStateChange', ({ granted, reason }) => { /* … */ })
session.on('error', (err) => { /* … */ })
off()

注释:

  • 与 requireConsent 删除/false自动赠款 ['core','governance','extension'] 开始.
  • 当未获准进入(或该方法的类别未获准)时,入境 apiCalls 以 errorCode: '-3' {\fn黑体\fs20\shad2\2ah82\3ah20\4ah33\fscx95\3ch592001\be1}在你之前 {\fn黑体\fs20\shad2\2ah82\3ah20\4ah33\fscx95\3ch592001\be1}你已经.. apiCallHandler 运行.
  • 扔出一个处理器被浮出DApp errorCode: '-2'。 。 。 .
  • 会议执行 Symbol.dispose这样 using session = createWalletConnectorSession(...) 在支持的地方工作.

远程签名( 请求方)

useSigningRequestSender 让钱包要求另一个对齐实例来签名交易。 这需要 configureSigningTransport(...) 和活跃的NATS连接.

import {
  configureSigningTransport,
  useSigningRequestSender,
} from '@eternl/hub-wallet-sdk'

// Configure once, globally:
configureSigningTransport({
  getDeviceInfo:        () => myDeviceInfo,
  getMyDeviceId:        () => myDeviceId,
  getMyPeerId:          () => myPeerId,
  getSessionKey:        (deviceId) => sessionKeysByDevice[deviceId],   // base64 raw key | undefined
  getPairCryptoContext: async (deviceId) => ({
    pairingId,
    pinAadBytes,        // Uint8Array — first 8 bytes of SHA-256(pin)
  }),
  getNextSeq:           (pairingId) => nextSeqFor(pairingId),          // bigint, monotonic per pairing
})

const { requestRemoteSigning } = useSigningRequestSender()

const result = await requestRemoteSigning(targetInstance, transactionCBOR, {
  walletPubKeyHash: 'sha256-hex-of-wallet-pubkey',
  // walletId?: explicit id to skip the pubKeyHash lookup
  // timeoutMs?: overrides SIGNING_TIMEOUT_MS (default 120_000)
})

// result.status: 'idle' | 'requesting' | 'waiting' | 'approved' | 'rejected' | 'timeout' | 'error'
if (result.status === 'approved') {
  console.log('signed tx:', result.signedTxCBOR, 'witness:', result.witnessSet)
} else {
  console.error('signing failed:', result.error)
}

反应方请看 useSigningRequestHandler (解码/解码输入) signing.request.encrypted和 useSigningResponseSender (发布加密响应).

存在信标和原始流存在

import {
  getWalletPresenceBeacon,
  createWalletPresenceCClient,
} from '@eternl/hub-wallet-sdk'

// Process-wide beacon — fans tab-visibility / page-unload transitions to all
// registered sessions. WalletConnectorSession registers itself automatically.
const beacon = getWalletPresenceBeacon()
console.log('registered sessions:', beacon.size)

// Standalone raw-stream (Option C) presence client (usually you'd use the
// session's `presenceC` option instead of building this directly):
const presenceC = createWalletPresenceCClient({
  pairId,
  deviceId,
  tabId,
  getNc: () => useNatsClient().getNatsConnection(),  // live nats.ws connection or null
  onPeerEvent: (event) => console.log('peer presence:', event.classification),
})
presenceC.start()
// … later
presenceC.stop()

低级可堆肥

使用 Nats 客户端

一个全流程的NATS WebSocket客户端. 状态通过 获取器,以及请求/答复用途 subscribeAndRequest (没有) request() 页:1.

import { useNatsClient } from '@eternl/hub-wallet-sdk'

const nats = useNatsClient()
nats.configure({ getNatsUrl: () => 'wss://hub.de-5.eternl.art/nats', getAuthenticator })
await nats.connect()

// State getters
nats.connectionStatus()   // 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error'
nats.isConnected()        // boolean
nats.errorMessage()       // string
nats.reconnectAttempts()  // number

// Subscribe (JSON-parsed + schema-validated). Returns a Subscription | null.
const sub = nats.subscribe('hub.device.peer-id.message', (data) => {
  console.log('received:', data)
})

// Raw subscribe (no JSON parse/validation) — returns { unsubscribe } | null
const rawSub = nats.subscribeRaw('presence_out.pair.dapp', (bytes: Uint8Array) => { /* … */ })

// Publish
await nats.publish('hub.device.peer-id.message', { type: 'hello' })
await nats.publishRaw('subject', new Uint8Array([1, 2, 3]))

// Request/response (unique reply subject per call)
const res = await nats.subscribeAndRequest<MyResponse>(
  'hub.responses',          // responseSubject (a unique suffix is appended)
  'hub.requests',           // requestSubject
  { query: 'status' },      // requestData (a `replyTo` field is injected)
  { timeout: 5000 },
)
if (res.success) console.log(res.data)
else console.error(res.error)

// Cleanup
nats.unsubscribe('hub.device.peer-id.message')
nats.unsubscribeAll()
await nats.disconnect()

使用复制

ECDH(P-256) + HKDF-SHA256 会话键衍生和AES-256-GCM AEAD, 与 @eternl/hub-core v2. 现有 没有 deriveSharedSecret; v2 管道为 deriveSharedSecretRaw → deriveSessionKeyHKDF加密为 PIN 输入: 每个帧的 AAD 是 utf8(pairingId) || SHA-256(pin)[:8] || be64(seq)。 。 。 .

import { useEncryption } from '@eternl/hub-wallet-sdk'

const enc = useEncryption()

// Handshake
const keyPair    = await enc.generateKeyPair()                       // KeyPair | null
const myPubB64   = await enc.exportPublicKey(keyPair!.publicKey)      // string | null
const peerPub    = await enc.importPublicKey(peerPubB64)             // CryptoKey | null

// v2 derivation
const shared     = await enc.deriveSharedSecretRaw(keyPair!.privateKey, peerPub!) // Uint8Array | null
const sas6       = await enc.deriveSAS6(shared!, pin, pairingId)     // 6-digit string for UI confirm
const session    = await enc.deriveSessionKeyHKDF(shared!, pairingId, pin)        // SessionKey | null
// session.key — non-extractable CryptoKey;  session.raw — base64 raw key (persist with care)

// Encrypt — pass a CryptoKey and a context { pairingId, pin | pinAadBytes, seq }
let seq = 1n
const payload = await enc.encryptJSON(
  { hello: 'world' },
  session!.key,
  { pairingId, pin, seq },          // OR { pairingId, pinAadBytes, seq } for PIN-less callers
)

// Decrypt — seq is read from the payload, so the context omits it
const plain = await enc.decryptJSON<{ hello: string }>(
  payload!,
  session!.key,
  { pairingId, pin },               // OR { pairingId, pinAadBytes }
)

// Re-import a persisted raw key as a non-extractable CryptoKey
const imported = await enc.importSessionKey(session!.raw)            // CryptoKey | null

enc.cleanup()

EncryptedPayload 是一个 v2 信封 : { version: 2, iv, authTag, encrypted, algorithm, timestamp, messageId, pairingId, seq } (何处) seq 是一个小数字符串。 解密任何非v2载荷的硬故障.

重放保护

记忆中,每..pairId 以 TTL 窗口消除信件复制. checkAndRecordMessage 实值 同步 返回时 { valid, error? } (没有) .reason 和无所等待.

import {
  generateMessageId,
  checkAndRecordMessage,
  clearReplayCache,
} from '@eternl/hub-wallet-sdk'

const messageId = generateMessageId()              // 'msg_…'
const timestamp = new Date().toISOString()

// Signature: checkAndRecordMessage(pairId, messageId, timestamp)
const check = checkAndRecordMessage('pair-id-123', messageId, timestamp)
if (!check.valid) {
  console.warn('rejected:', check.error)           // e.g. 'Replay attack detected: duplicate messageId'
}

clearReplayCache('pair-id-123')

(关于命名兼容性, checkAndRecordMessage 也作为 checkAndRecordMessageAsync ——尽管有名字,它仍然同步. )

使用会话密钥缓存

切片不可提取 CryptoKey键入 deviceId说明 importSessionKey 带 deviceId 第一个,然后是基础64生键.

import {
  importSessionKey,
  getCachedKey,
  hasCachedKey,
  clearCachedKey,
  getCacheStats,
} from '@eternl/hub-wallet-sdk'

const key = await importSessionKey(deviceId, rawBase64)   // (deviceId, rawBase64) → CryptoKey | null

if (hasCachedKey(deviceId)) {
  const cached = getCachedKey(deviceId)                   // CryptoKey | null
}

const stats = getCacheStats()                             // { size: number; deviceIds: DeviceId[] }
clearCachedKey(deviceId)

使用MessageAuth 数据

HMAC-SHA256认证在 RFC-8785-canonicalized messages 上,由 Base64 生会话密钥字符串键入.

import {
  signMessage,
  verifyMessage,
  createSignedMessage,
  verifyAndUnwrap,
} from '@eternl/hub-wallet-sdk'

const sig    = await signMessage({ type: 'presence', online: true }, sessionKeyRaw) // string | null
const ok     = await verifyMessage({ type: 'presence', online: true, signature: sig! }, sessionKeyRaw)
const signed = await createSignedMessage({ type: 'presence', online: true }, sessionKeyRaw) // T & { signature } | null
const orig   = await verifyAndUnwrap(signed!, sessionKeyRaw)  // T | null (null if invalid)

使用 Nats 校正

消息结构验证和类型守护.

import {
  validateNatsMessage,
  isValidEncryptedPayload,
  parseAndValidatePayload,
} from '@eternl/hub-wallet-sdk'

const v = validateNatsMessage(message)   // { valid: boolean; error?: string; type?: string }
if (isValidEncryptedPayload(payload)) { /* … */ }
const parsed = parseAndValidatePayload(jsonString)

存储

这个 HubStorage 界面使用 getItem 编号 : setItem 编号 : removeItem (带有可选内容) clear),并同时支持同步(localStorage)和Async(IndexedDB)后端.

import {
  createLocalStorage,
  createMemoryStorage,
  isLocalStorageAvailable,
  type HubStorage,
} from '@eternl/hub-wallet-sdk'

interface HubStorage {
  getItem(key: string): string | null | Promise<string | null>
  setItem(key: string, value: string): void | Promise<void>
  removeItem(key: string): void | Promise<void>
  clear?(): void | Promise<void>
}

// Built-in adapters
initHub({ network: 'mainnet', storage: createLocalStorage('my-wallet') })
initHub({ network: 'mainnet', storage: createMemoryStorage() })

// Custom (e.g. IndexedDB) adapter
const customStorage: HubStorage = {
  getItem:    (key) => myDB.get(key),
  setItem:    (key, value) => myDB.set(key, value),
  removeItem: (key) => myDB.delete(key),
}
initHub({ network: 'mainnet', storage: customStorage })

如果没有提供存储, initHub 可用时使用本地Storage,否则将返回内存.

公用事业

加农化(RFC 8785)

import { canonicalize, createSigningPayload } from '@eternl/hub-wallet-sdk'

canonicalize({ b: 2, a: 1 })                       // '{"a":1,"b":2}'
createSigningPayload(message, ['signature'])       // canonical string with fields excluded

安全身份证

import { generateSecureId, generateSecureMessageId, assertCryptoCapabilities } from '@eternl/hub-wallet-sdk'

assertCryptoCapabilities()         // throws if WebCrypto is unavailable
const id  = generateSecureId()     // 32-char hex (derived from crypto.randomUUID / getRandomValues)
const mid = generateSecureMessageId()  // 'msg_…' (alias of generateMessageId)

协议常数

所有协议常数导出为 获取函数 返回已解析值(默认值或通过 initHub({ constants: … }):

import {
  CONNECTION_TIMEOUT_MS,           // () => 10_000
  SIGNING_TIMEOUT_MS,              // () => 120_000
  REPLAY_PROTECTION_TTL_MS,        // () => 300_000
  MAX_PAYLOAD_SIZE_BYTES,          // () => 1_048_576
  PRESENCE_HEARTBEAT_INTERVAL_MS,  // () => 5_000
  DEFAULT_HUB_URL,                 // 'wss://hub.de-5.eternl.art/nats' (string constant)
} from '@eternl/hub-wallet-sdk'

const timeout = CONNECTION_TIMEOUT_MS()   // call them

协议类型和权限

SDK从中再导出全套协议类型 @eternl/hub-core 及其自己的模块,加上 Permission 页:1 AccountInfo数字 :

import type {
  DeviceId, PeerId, PairId, PairingId,
  DeviceInfo, PairedInstance, WalletRegistryEntry,
  SigningRequestMessage, EncryptedSigningRequestMessage,
  EncryptedPayload, SessionKey, KeyPair,
  ValidationResult, ReplayValidationResult,
  AccountInfo,
} from '@eternl/hub-wallet-sdk'

import { Permission } from '@eternl/hub-wallet-sdk'

const granted = [Permission.ADDRESS_READ, Permission.SIGN_TX, Permission.SIGN_DATA]

安保模式(摘要)

  • 端到端加密 ——AES-256-GCM 有随机的12字节IV和16字节Auth标记.
  • PIN 绑定会话键 —— 说 HKDF-SHA256 (P-256)共同的秘密,与 SHA-256(utf8(pin) || pairingId); AAD 绑定 pairingId, (中文(简体) ), SHA-256(pin)[:8]单调 seq. 没有PIN,会议键无法仅取自欧洲人权法院的记录.
  • 标准6 ——6位数的短认证字符串,用于波段外配对确认.
  • 重放保护 每个pairId 以 TTL 窗口和时钟- swew 容忍来消除信件重复 .
  • HMAC 认证 ——HMAC-SHA256上传了RFC-8785卡通化消息.
  • 有效载荷验证 ——大小限制和对入境的NATS消息的检查.
  • 严格 v2 线 ——预v2加密有效载荷被硬拒绝(无静降级).

许可证

商业来源许可证1.1(BUSL-1.1) (中文(简体) ). 见 自由主义。 。 。 .

许可是Tastenkunst GmbH。 额外使用赠款 : None - 你可以复制、修改和制作 非生产 使用此软件包。 生产/商业用途需要从塔斯滕昆斯特获得单独的许可证。 在"更改日期"(每个版本首次出版的四周年)上,该版本会转换为GPL-2.0-或-后期.

联系人 : https://tastenkunst.com/ (中文(简体) )

版本与发布记录

@eternl/hub-wallet-sdk 共发布 69 个版本,首次发布于 2026/05/08;过去 12 个月发布了 69 个版本。

版本发布日期距今
0.55.0latest2026/11/103 天前
0.54.02026/11/103 天前
0.53.02026/11/103 天前
0.52.02026/11/103 天前
0.51.02026/11/104 天前
0.50.02026/11/094 天前

关于 @eternl/hub-wallet-sdk 的常见问题

@eternl/hub-wallet-sdk 是什么?

Eternl Hub SDK用于钱包开发者.

如何安装 @eternl/hub-wallet-sdk?

在项目目录运行 npm install @eternl/hub-wallet-sdk,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@nats-io/kv(3.4.0)、@nats-io/jetstream(3.4.0)、@nats-io/nats-core(3.4.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@eternl/hub-wallet-sdk 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@eternl/hub-wallet-sdk 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@eternl/hub-wallet-sdk 可以商用吗?

@eternl/hub-wallet-sdk 使用 BUSL-1.1 许可。声明的许可为 BUSL-1.1,请阅读许可原文确认使用条件。以上为概括,不构成法律意见,请以许可原文为准。

@eternl/hub-wallet-sdk 的下载量有多少?

根据 npm 官方下载统计,@eternl/hub-wallet-sdk 在 2026/10/14 – 2026/11/12 这 30 天内被下载 2,487 次,日均约 83 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@eternl/hub-wallet-sdk 还在维护吗?

最新版本 0.55.0 发布于 2026/11/10(3 天前);至今共发布 69 个版本,其中过去 12 个月发布了 69 个;首次发布于 2026/05/08。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。