UNPKG

herlina-kit

Version:

protocol untuk menghubungkan DApp Vexanium ke dompet Herlina

163 lines (143 loc) 4.68 kB
import {Base64u, IdentityProof, SigningRequest} from "@wharfkit/signing-request"; import {Serializer} from "@wharfkit/antelope"; import {Peer} from "peerjs"; import zlib from "pako"; import {WalletSession} from "./WalletSession.js"; import {loadSession, saveSession} from "./session-store.js"; /** * Membuat sambungan dengan signal server. * Dapatkan WalletSession */ export class Herlina { /** * @type {Peer} */ #peer; #peerOptions = {}; #peerId; #listeners = new Map(); #identityArgs = {}; constructor() { this.#peerOptions.config = { iceServers: [ {urls: "stun:stun.l.google.com:19302"}, {urls: "stun:stun1.l.google.com:3478"}, {urls: "stun:stun.relay.metered.ca:80"}, { urls: "turn:asia.relay.metered.ca:80", username: "b66cd40a117bddb5cde924ab", credential: "4jRmuTehVCZ2a/S+" } ], sdpSemantics: "unified-plan" }; this.#identityArgs.scope = "vexanium"; this.#identityArgs.chainId = WalletSession.ChainID; } /** * tambah stun atau turn server * @param {RTCIceServer} server */ addIceServer(server) { this.#peerOptions.config.iceServers.push(server); } /** * setel alamat signal server * @param host * @param port */ setServer(host, port) { this.#peerOptions.host = host; if (port) this.#peerOptions.port = port; } /** * Setel listeners untuk peer events * @param {string} event open, close, disconnected, error, session * @param {Function} func */ on(event, func) { this.#listeners.set(event, func); } /** * buat sambungan dengan signal server. * jawaban dari wallet bisa didengarkan dengan event session * * @see on * @see createLoginRequest */ async connect() { if (!this.#peerId) { const session = loadSession(); this.#peerId = session ? session.peerID : `VEX-${window.crypto.randomUUID()}`; } this.#peer = new Peer(this.#peerId, this.#peerOptions); this.#peer.on("connection", this.#onConnection.bind(this)); this.#listeners.forEach((func, key) => { this.#peer.on(key, func); }); } disconnect() { if (this.#peer) this.#peer.disconnect(); } destroy() { if (this.#peer) this.#peer.destroy(); } reconnect() { if (this.#peer) this.#peer.reconnect(); } isDisconnected() { return (this.#peer) ? this.#peer.disconnected : true; } isDestroyed() { return (this.#peer) ? this.#peer.destroyed : true; } /** * membuat vsr untuk login. * @param {string} name nama aplikasi * @param {string} icon url icon aplikasi * @return {string} vsr yang bisa dipakai untuk data kode qr atau query url */ createLoginRequest(name, icon) { this.#peerId = `VEX-${window.crypto.randomUUID()}`; const session = loadSession(); if (session) { const [actor, perm] = session.permission.split("@"); this.#identityArgs.account = actor; this.#identityArgs.permission = perm; this.#peerId = session.peerID; } const request = SigningRequest.identity(this.#identityArgs, {zlib}); request.setInfoKey("pi", this.#peerId); request.setInfoKey("na", name); request.setInfoKey("ic", icon); request.setInfoKey("do", window.location.origin); if (session) { request.setInfoKey("auth", session.auth); } return request.encode(true, false, "vsr:"); } /** * * @param {import('peerjs').DataConnection} conn */ #onConnection(conn) { conn.once("data", payload => { if (payload.code === 'LOGIN_OK') { const auth = payload.result.auth; const proof = Serializer.decode({data: Base64u.decode(auth), type: IdentityProof}); const session = new WalletSession(conn); session.permissionLevel = proof.signer; // simpan session saveSession({ peerID: this.#peerId, permission: proof.signer.toString(), expiration: proof.expiration, auth }); // kirim notify const func = this.#listeners.get("session"); if (func) func(session, proof); } }); } }