import { sha256 } from "@noble/hashes/sha2.js"; import { openAuthPopup } from "./ui/connect/AuthPopup"; import { OmniToken, WalletType } from "./omni/config"; import { OmniConnector } from "./OmniConnector"; import { Intents } from "./omni/Intents"; import { ReviewFee } from "./omni/bridge"; import { Token } from "./omni/token"; export interface AuthCommitment { tradingAddress: string; signed: Record; address: string; publicKey: string; chainId: WalletType; seed: string; } export interface SignedAuth { signed: Record; address: string; publicKey: string; chainId: WalletType; seed: string; } export abstract class OmniWallet { constructor(readonly connector: OmniConnector) {} abstract address: string; abstract publicKey?: string; abstract omniAddress: string; abstract type: WalletType; async disconnect() { if (!this.connector) throw new Error("Connector not implemented"); await this.connector.disconnect(); } abstract transferFee(token: Token, receiver: string, amount: bigint): Promise; abstract transfer(args: { token: Token; receiver: string; amount: bigint; comment?: string; gasFee?: ReviewFee }): Promise; abstract signIntentsWithAuth(domain: string, intents?: Record[]): Promise; abstract signIntents(intents: Record[], options?: { nonce?: Uint8Array; deadline?: number }): Promise>; abstract fetchBalance(chain: number, address: string): Promise; abstract fetchBalances(chain?: number, whitelist?: string[]): Promise>; async executeIntents(intents: Record[], hashes: string[] = []) { const signed = await this.signIntents(intents); return await Intents.publishSignedIntents([signed], hashes); } get icon() { return this.connector?.icon; } get intents() { return new Intents(this.connector.wibe3).attachWallet(this); } async auth(domain: string, intents?: Record[], then?: (signed: SignedAuth) => Promise): Promise { return openAuthPopup(this, async () => { const signed = await this.signIntentsWithAuth(domain, intents); return (await then?.(signed)) ?? (signed as T); }); } async pay({ token, amount, recipient, paymentId }: { token: OmniToken; amount: number; recipient: string; paymentId: string }) { const nonce = new Uint8Array(sha256(new TextEncoder().encode(paymentId))).slice(0, 32); return this.intents.attachNonce(nonce).transfer({ recipient, token, amount }).execute(); } async waitUntilBalance(need: Record, receiver: string, attempts = 0) { if (attempts > 120) throw "Balance is not enough"; const assets = Object.keys(need) as string[]; const balances = await Intents.getIntentsBalances(assets, receiver); if (assets.every((asset) => (balances[asset] || 0n) >= (need[asset] || 0n))) return; await new Promise((resolve) => setTimeout(resolve, 1000)); await this.waitUntilBalance(need, receiver, attempts + 1); } async getIntentsBalance(asset: string, receiver: string): Promise { const balances = await Intents.getIntentsBalances([asset], receiver); return balances[asset] || 0n; } async getAssets() { if (!this.omniAddress) return {}; const assets = await Intents.getIntentsAssets(this.omniAddress); const balances = await Intents.getIntentsBalances(assets, this.omniAddress); return balances; } }