UNPKG

@windoge98/pnp-phantom

Version:

Phantom wallet adapter for Plug-n-Play

444 lines (443 loc) 38.7 kB
import { BaseSiwxAdapter, Adapter, deriveAccountId, formatSiwsMessage, createAdapterExtension } from "@windoge98/plug-n-play"; import { formatSiwsMessage as formatSiwsMessage2 } from "@windoge98/plug-n-play"; import { AnonymousIdentity } from "@dfinity/agent"; import { PhantomWalletAdapter } from "@solana/wallet-adapter-phantom"; import { WalletAdapterNetwork, WalletReadyState } from "@solana/wallet-adapter-base"; import { Connection, LAMPORTS_PER_SOL } from "@solana/web3.js"; import { Ed25519KeyIdentity } from "@dfinity/identity"; import bs58 from "bs58"; const idlFactory = ({ IDL }) => { const RuntimeFeature = IDL.Variant({ "IncludeUriInSeed": IDL.Null, "DisablePrincipalToSolMapping": IDL.Null, "DisableSolToPrincipalMapping": IDL.Null }); IDL.Record({ "uri": IDL.Text, "runtime_features": IDL.Opt(IDL.Vec(RuntimeFeature)), "domain": IDL.Text, "statement": IDL.Opt(IDL.Text), "scheme": IDL.Opt(IDL.Text), "salt": IDL.Text, "session_expires_in": IDL.Opt(IDL.Nat64), "targets": IDL.Opt(IDL.Vec(IDL.Text)), "chain_id": IDL.Opt(IDL.Text), "sign_in_expires_in": IDL.Opt(IDL.Nat64) }); const Principal = IDL.Vec(IDL.Nat8); const Address = IDL.Text; const GetAddressResponse = IDL.Variant({ "Ok": Address, "Err": IDL.Text }); const GetPrincipalResponse = IDL.Variant({ "Ok": Principal, "Err": IDL.Text }); const PublicKey = IDL.Vec(IDL.Nat8); const SessionKey = PublicKey; const Timestamp = IDL.Nat64; const Delegation = IDL.Record({ "pubkey": PublicKey, "targets": IDL.Opt(IDL.Vec(IDL.Principal)), "expiration": Timestamp }); const SignedDelegation = IDL.Record({ "signature": IDL.Vec(IDL.Nat8), "delegation": Delegation }); const GetDelegationResponse = IDL.Variant({ "Ok": SignedDelegation, "Err": IDL.Text }); const SiwsSignature = IDL.Text; const Nonce = IDL.Text; const CanisterPublicKey = PublicKey; const LoginDetails = IDL.Record({ "user_canister_pubkey": CanisterPublicKey, "expiration": Timestamp }); const LoginResponse = IDL.Variant({ "Ok": LoginDetails, "Err": IDL.Text }); const SiwsMessage = IDL.Record({ "uri": IDL.Text, "issued_at": IDL.Nat64, "domain": IDL.Text, "statement": IDL.Text, "version": IDL.Nat32, "chain_id": IDL.Text, "address": Address, "nonce": IDL.Text, "expiration_time": IDL.Nat64 }); const PrepareLoginResponse = IDL.Variant({ "Ok": SiwsMessage, "Err": IDL.Text }); return IDL.Service({ "get_address": IDL.Func([Principal], [GetAddressResponse], ["query"]), "get_caller_address": IDL.Func([], [GetAddressResponse], ["query"]), "get_principal": IDL.Func([Address], [GetPrincipalResponse], ["query"]), "siws_get_delegation": IDL.Func( [Address, SessionKey, Timestamp], [GetDelegationResponse], ["query"] ), "siws_login": IDL.Func( [SiwsSignature, Address, SessionKey, Nonce], [LoginResponse], [] ), "siws_prepare_login": IDL.Func([Address], [PrepareLoginResponse], []) }); }; const _PhantomAdapter = class _PhantomAdapter extends BaseSiwxAdapter { constructor(args) { super(args); this.walletName = "Phantom"; this.id = "phantom"; this.phantomAdapter = null; this.solanaAddress = null; this.connectingPromise = null; this.handlePhantomConnect = (publicKey) => { this.solanaAddress = publicKey.toBase58(); this.logger.debug(`Phantom wallet connected`, { address: this.solanaAddress }); }; this.handlePhantomDisconnect = () => { if (this.state !== Adapter.Status.DISCONNECTING && this.state !== Adapter.Status.DISCONNECTED) { this.disconnect(); } }; this.handlePhantomError = (error) => { this.logger.error(`Phantom wallet error`, error, { wallet: this.walletName }); this.setState(Adapter.Status.ERROR); this.disconnect(); }; this.id = args.adapter.id; this.walletName = args.adapter.walletName; this.logo = args.adapter.logo; this.config = args.config; this.initializeConnection(); if (this.isBrowser()) { this.initializePhantomAdapter(); } this.setState(Adapter.Status.READY); } resolveProviderCanisterId() { const cfg = this.config; const canisterId = cfg.providerCanisterId || cfg.siwsProviderCanisterId; if (!canisterId) { throw new Error("SIWS provider canister ID not configured."); } return String(canisterId); } isBrowser() { return typeof window !== "undefined" && typeof window.document !== "undefined"; } initializeConnection() { const network = this.config.solanaNetwork || WalletAdapterNetwork.Mainnet; const endpoint = this.config.rpcEndpoint || (network === WalletAdapterNetwork.Mainnet ? "https://api.mainnet-beta.solana.com" : "https://api.devnet.solana.com"); this.solanaConnection = new Connection(endpoint); } initializePhantomAdapter() { this.phantomAdapter = new PhantomWalletAdapter(); this.setupWalletListeners(); } setupWalletListeners() { if (!this.phantomAdapter) return; this.phantomAdapter.on("connect", this.handlePhantomConnect); this.phantomAdapter.on("disconnect", this.handlePhantomDisconnect); this.phantomAdapter.on("error", this.handlePhantomError); } removeWalletListeners() { if (!this.phantomAdapter) return; this.phantomAdapter.off("connect", this.handlePhantomConnect); this.phantomAdapter.off("disconnect", this.handlePhantomDisconnect); this.phantomAdapter.off("error", this.handlePhantomError); } destroy() { this.removeWalletListeners(); } async isConnected() { if (!this.phantomAdapter) return false; return this.phantomAdapter.connected && this.identity !== null && !this.identity.getPrincipal().isAnonymous(); } async connect() { if (this.connectingPromise) return this.connectingPromise; this.connectingPromise = (async () => { if (!this.isBrowser()) { throw new Error("Cannot connect to Phantom wallet in non-browser environment"); } this.resolveProviderCanisterId(); if (this.identity && this.state === Adapter.Status.CONNECTED) { const principal = this.identity.getPrincipal(); return { owner: principal.toText(), subaccount: deriveAccountId(principal) }; } this.setState(Adapter.Status.CONNECTING); try { if (!this.phantomAdapter) { this.initializePhantomAdapter(); } if (!this.phantomAdapter) { throw new Error("Failed to initialize Phantom adapter"); } if (!this.phantomAdapter.connected) { this.logger.debug(`Connecting to Phantom wallet...`); if (this.phantomAdapter.readyState === WalletReadyState.NotDetected) { throw new Error("Phantom wallet is not installed. Please install the Phantom browser extension."); } try { await this.phantomAdapter.connect(); } catch (error) { this.logger.error(`Phantom connection error`, error, { wallet: this.walletName }); if (error.name === "WalletWindowClosedError" || error.message?.includes("User rejected the request") || error.message?.includes("Wallet closed")) { this.setState(Adapter.Status.DISCONNECTED); throw new Error("Connection cancelled by user"); } this.setState(Adapter.Status.ERROR); throw error; } } if (!this.phantomAdapter.publicKey) { throw new Error("Phantom wallet connected but no public key available"); } if (!("signMessage" in this.phantomAdapter)) { throw new Error(`Phantom wallet does not support message signing required for SIWS`); } const address = this.phantomAdapter.publicKey.toBase58(); this.solanaAddress = address; await this.storeExternalAddress(`${this.id}-solana-address`, address); const { identity, sessionKey } = await this.performSiwsLogin(address, this.phantomAdapter); this.identity = identity; this.sessionKey = sessionKey; const principal = identity.getPrincipal(); this.setState(Adapter.Status.CONNECTED); return { owner: principal.toText(), subaccount: deriveAccountId(principal) }; } catch (error) { this.logger.error(`Connect process failed`, error, { wallet: this.walletName }); this.setState(Adapter.Status.ERROR); throw error; } finally { this.connectingPromise = null; } })(); return this.connectingPromise; } async createSiwsProviderActor(identity) { const id = identity ?? new AnonymousIdentity(); return this.createProviderActor(idlFactory, id); } async signSiwsMessage(siwsMessage, adapter) { const messageText = formatSiwsMessage(siwsMessage); const messageBytes = new TextEncoder().encode(messageText); if (!("signMessage" in adapter)) { throw new Error(`Phantom wallet does not support signMessage.`); } const signatureBytes = await adapter.signMessage(messageBytes); if (signatureBytes instanceof Uint8Array) { return bs58.encode(signatureBytes); } if (signatureBytes instanceof ArrayBuffer) { return bs58.encode(new Uint8Array(signatureBytes)); } try { const arr = Array.isArray(signatureBytes) ? signatureBytes : Object.values(signatureBytes); return bs58.encode(new Uint8Array(arr)); } catch (e) { this.logger.error(`Error encoding signature`, e, { wallet: this.walletName }); throw new Error(`Failed to encode signature from Phantom: ${e.message}`); } } async performSiwsLogin(address, adapter) { const actor = await this.createSiwsProviderActor(); const prepareResult = await actor.siws_prepare_login(address); if ("Err" in prepareResult) { throw new Error(`SIWS Prepare Login failed: ${prepareResult.Err}`); } const signature = await this.signSiwsMessage(prepareResult.Ok, adapter); const sessionIdentity = Ed25519KeyIdentity.generate(); const sessionPublicKeyDer = sessionIdentity.getPublicKey().toDer(); const loginResult = await actor.siws_login( signature, address, new Uint8Array(sessionPublicKeyDer), prepareResult.Ok.nonce ); if ("Err" in loginResult) { throw new Error(`SIWS Login failed: ${loginResult.Err}`); } const delegationResult = await actor.siws_get_delegation( address, new Uint8Array(sessionPublicKeyDer), loginResult.Ok.expiration ); if ("Err" in delegationResult) { throw new Error(`SIWS Get Delegation failed: ${delegationResult.Err}`); } const identity = this.createDelegationIdentity( delegationResult.Ok, sessionIdentity, new Uint8Array(loginResult.Ok.user_canister_pubkey).buffer ); return { identity, sessionKey: sessionIdentity }; } async disconnectInternal() { await super.disconnectInternal(); if (this.phantomAdapter) { try { if (this.phantomAdapter.connected) { this.removeWalletListeners(); await this.phantomAdapter.disconnect(); this.setupWalletListeners(); } } catch (error) { this.logger.warn(`Error during Phantom disconnect`, { error, wallet: this.walletName }); } } this.identity = null; this.solanaAddress = null; } async getPrincipal() { if (!this.identity) { throw new Error("Not connected or SIWS flow not completed."); } return this.identity.getPrincipal().toText(); } async getAccountId() { const principal = await this.getPrincipal(); if (!principal) throw new Error("Principal not available to derive account ID"); return deriveAccountId(principal); } async getSolanaAddress() { if (!this.solanaAddress) { throw new Error("Not connected or Solana address not available."); } return this.solanaAddress; } async getAddresses() { const principal = this.identity?.getPrincipal(); return { sol: { address: this.solanaAddress, network: this.config.solanaNetwork }, icp: { address: principal?.toText(), subaccount: principal ? deriveAccountId(principal) : void 0 } }; } createActorInternal(canisterId, idl, options) { const requiresSigning = options?.requiresSigning ?? true; if (requiresSigning && !this.identity) { throw new Error( "Cannot create signed actor: Not connected or SIWS flow not completed." ); } const agent = this.buildHttpAgentSync({ identity: this.identity ?? void 0 }); return this.createActorWithAgent(agent, canisterId, idl); } async getSolBalance() { if (!this.phantomAdapter?.publicKey) { throw new Error("Wallet not connected"); } try { const balance = await this.solanaConnection.getBalance(this.phantomAdapter.publicKey); const solAmount = balance / LAMPORTS_PER_SOL; return { amount: solAmount }; } catch (error) { this.logger.error(`Failed to get SOL balance`, error, { wallet: this.walletName }); throw error; } } async estimateTransactionFee(transaction) { if (!this.phantomAdapter?.publicKey) { throw new Error("Wallet not connected"); } try { const { blockhash } = await this.solanaConnection.getLatestBlockhash(); transaction.recentBlockhash = blockhash; transaction.feePayer = this.phantomAdapter.publicKey; const message = transaction.compileMessage(); const fee = await this.solanaConnection.getFeeForMessage(message, "confirmed"); if (fee.value === null) { throw new Error("Unable to estimate fee"); } return fee.value / LAMPORTS_PER_SOL; } catch (error) { this.logger.error(`Failed to estimate transaction fee`, error, { wallet: this.walletName }); throw error; } } async getTransactionStatus(signature) { try { const status = await this.solanaConnection.getSignatureStatus(signature); if (!status.value) { return { confirmed: false }; } return { confirmed: status.value.confirmationStatus === "confirmed" || status.value.confirmationStatus === "finalized", slot: status.value.slot, err: status.value.err }; } catch (error) { this.logger.error(`Failed to get transaction status`, error, { wallet: this.walletName, signature }); throw error; } } async onStorageRestored(_sessionKey, _delegationChain) { const storedSolanaAddress = await this.readExternalAddress(`${this.id}-solana-address`); if (storedSolanaAddress) this.solanaAddress = storedSolanaAddress; } async onClearStoredSession() { this.solanaAddress = null; await this.storage.remove(`${this.id}-solana-address`); } }; _PhantomAdapter.supportedChains = [ Adapter.Chain.ICP, Adapter.Chain.SOL ]; let PhantomAdapter = _PhantomAdapter; const phantomLogo = "data:image/webp;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAAH0CAYAAADL1t+KAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAB9KADAAQAAAABAAAB9AAAAAB3bs6AAABAAElEQVR4Ae3dZ3Mkx5ng8QfobjSAhhvvvfc0Mxz6oadIURRFrnZXWht3b+6T6DPoxV3E7kXo7lZaakVRIil6M+QMOeQ4DsdyvPcYeNMALp8eQgP0tK+q7qysf0Z0AN1dVZ35ywKezqo0db/+1fkxISGAAAIIIIBAqAXqQ517Mo8AAggggAACGQECOicCAggggAACDggQ0B2oRIqAAAIIIIAAAZ1zAAEEEEAAAQcECOgOVCJFQAABBBBAgIDOOYAAAggggIADAgR0ByqRIiCAAAIIIEBA5xxAAAEEEEDAAQECugOVSBEQQAABBBAgoHMOIIAAAggg4IAAAd2BSqQICCCAAAIIENA5BxBAAAEEEHBAgIDuQCVSBAQQQAABBAjonAMIIIAAAgg4IEBAd6ASKQICCCCAAAIEdM4BBBBAAAEEHBAgoDtQiRQBAQQQQAABAjrnAAIIIIAAAg4IENAdqESKgAACCCCAAAGdcwABBBBAAAEHBAjoDlQiRUAAAQQQQICAzjmAAAIIIICAAwIEdAcqkSIggAACCCBAQOccQAABBBBAwAEBAroDlUgREEAAAQQQIKBzDiCAAAIIIOCAAAHdgUqkCAgggAACCBDQOQcQQAABBBBwQICA7kAlUgQEEEAAAQQI6JwDCCCAAAIIOCBAQHegEikCAggggAACBHTOAQQQQAABBBwQIKA7UIkUAQEEEEAAAQI65wACCCCAAAIOCBDQHahEioAAAggggAABnXMAAQQQQAABBwQI6A5UIkVAAAEEEECAgM45gAACCCCAgAMCBHQHKpEiIIAAAgggQEDnHEAAAQQQQMABAQK6A5VIERBAAAEEECCgcw4ggAACCCDggAAB3YFKpAgIIIAAAggQ0DkHEEAAAQQQcECAgO5AJVIEBBBAAAEECOicAwgggAACCDggQEB3oBIpAgIIIIAAAgR0zgEEEEAAAQQcECCgO1CJFAEBBBBAAAECOucAAggggAACDggQ0B2oRIqAAAIIIIAAAZ1zAAEEEEAAAQcECOgOVCJFQAABBBBAgIDOOYAAAggggIADAgR0ByqRIiCAAAIIIEBA5xxAAAEEEEDAAQECugOVSBEQQAABBBAgoHMOIIAAAggg4IAAAd2BSqQICCCAAAIIENA5BxBAAAEEEHBAgIDuQCVSBAQQQAABBAjonAMIIIAAAgg4IEBAd6ASKQICCCCAAAIEdM4BBBBAAAEEHBAgoDtQiRQBAQQQQAABAjrnAAIIIIAAAg4IENAdqESKgAACCCCAAAGdcwABBBBAAAEHBAjoDlQiRUAAAQQQQICAzjmAAAIIIICAAwIEdAcqkSIggAACCCBAQOccQAABBBBAwAEBAroDlUgREEAAAQQQIKBzDiCAAAIIIOCAAAHdgUqkCAgggAACCBDQOQcQQAABBBBwQICA7kAlUgQEEEAAAQQI6JwDCCCAAAIIOCBAQHegEikCAggggAACBHTOAQQQQAABBBwQIKA7UIkUAQEEEEAAAQI65wACCCCAAAIOCBDQHahEioAAAggggAABnXMAAQQQQAABBwQI6A5UIkVAAAEEEECAgM45gAACCCCAgAMCBHQHKpEiIIAAAgggQEDnHEAAAQQQQMABAQK6A5VIERBAAAEEECCgcw4ggAACCCDggEDcgTJQBAQQQKBsgXi8TpqazSNVL8nGOoknfniY/4r6e8y8r9vEE+Z55qc+v/1eXZ1IelhkeHgs80gP/fAz89y8N+m5ec88Hxock/7eURkZKTur7IBASQIE9JKY2AgBBMIkUGeuPaZa6qWl1TzaYuahPyc+YpkgXu0yjY2J9PWMSvctfYxIV+ftn/q8q3NEertHRbchIVCJAAG9EjX2QQABKwS0pdw+JSZTpsdkqnlMmRHP/N5hXquPWZHFSZnQ/KbMlwx9zJ5/979fbb3fvJaW61dG5NrltFy+YH43P0dHJx2GJwjkFLj7jMq5GS8igAACtRVINNTJtBkxmTYrLtNmxmT6TBO8zXO9HO5KipkvIdNN+fSxakMyU6x0ekyumMB+8WxaLp0bzgR5vYRPQiBbgICeLcJzBBCouYAGtqkmYM+cbR5z4jJjblw6psZEW7hRS/qFZe7CROYh0pRprV+9mJbzp4fl3KlhE+yHuS8ftZMiT3kJ6HlgeBkBBKon0GBa37PmxWX2goTMMZeiNYhrpzTS3QL1pn+AWunjvoebMh3uNLifPj4kZ48PS6+5R0+KpgABPZr1TqkRqKmAtrRnmNb3giUJmb+kQWaaFrgGKlL5AnorYvGKhsxD99b77icOD8qJI0PS00VwL180vHsQ0MNbd+QcgVAJJJN1JngnZOGyBvNISGMTETyICpxlvhzp46EnU3Lh7LAc3j8oJ01w13vxJLcFCOhu1y+lQ6CmAm0dMVm0PGEeDTLHXE6nFV7F6jBXQcbvvQ8+MyYH9wzIgW8GpM+MhSe5KUBAd7NeKRUCNROYZjqzLVnZkHlMNb3QSbUX0Ilz7n2oSTZuaZKjBwZk31cDcusmM9zUvmb8zQEB3V9PjoZAJAX0fvjSVQ2ydHWDaKucZKdAzPzHX3NPo6ze1CjHzX32PTv65cZVArudtVV+rgjo5ZuxBwIIGAFtfS9fk5Rl5tHWwf3wMJ0U2ikxU3erk5n7619/3mcmtCGwh6kOc+WVgJ5LhdcQQCCngE6nunxtUlasS2Ymd8m5ES+GRkADu15VWWKurhz7blC+3t6XmZY2NAUgo5MECOiTOHiCAALZArGYDotKyKqNjTJ/cSKSk7tkm7j2XAP7yvW3r7Yc+LpfdptL8bqYDClcAgT0cNUXuUWgagId02Kyxtxr1X/0jU3mPz7JeQGdoW/T1iZZaaad/eqTPjny7SCLxYSo1gnoIaossopA0AI6rEwnKVl3X+MPU40G/Ykc30aBpuZ62fZCi6w2V2U+/UsPHedsrKQceSKg50DhJQSiJtBs1gRfsykpa+5tzCw7GrXyU97cAjq97Gv/2pHpDb97R5+M0m8uN5QlrxLQLakIsoFALQR0zvT19zfKMtPb2cblRmthwmdOFtCrNvc/0iSLzOx+H/ypRzqvE9UnC9nzjIBuT12QEwSqIjB+WX2DmWRktmmBkRAoRWC6mWvgtX9pl8/e7TWT0wyWsgvbVFmAv+Yqg/NxCNRKQBfxWL0xKRs2N0lrO+PGa1UPYf7ceKJOnvxxS2alty/e72XZVssqk4BuWYWQHQT8Fmgy98c3mMvqa839cZ0ClISAV4G1Zra5aTPi8u4fuqWP5Vq9cvq2PwHdN0oOhIBdAjp726YHmmSVGYLE2uJ21Y0LudEOc6+aS/B/eb1brl5Ku1Ck0JeBgB76KqQACEwW0PHjuhCHTu3J6maTbXjmr4DOHPjyP7TJR6aznK6/TqqtAAG9tv58OgK+CUyZHpP7H27OTOWpM3+REKiGQDxeJ8/8tFV2ftQr+3cNVOMj+Yw8AgT0PDC8jEBYBLRFvtkMK1pqhp4RyMNSa27lU8+7h55KZeYw2PlRnzBpbG3ql4BeG3c+FQHPAtpTffOjzZmFUgjknjk5gA8CG02fjWRTvXzydg9TxvrgWe4hCOjlirE9AjUWaGyuy1xa157GTAZT48rg4+8S0E6YcRNZPjT31UdH73qbFwIUIKAHiMuhEfBTQO9VbtjSKPeYxTMaktwk99OWY/krsMx0yNT7Px++2U1Q95e24NEI6AV5eBOB2gvo5XRdf/yBx5sl1cqEMLWvEXJQisAys8766EiLfPRnLr+X4uXHNgR0PxQ5BgIBCcxdmDCdjZpl+iz+VAMi5rABCugX0UGzrvrn7/UG+CkcelyA/xLjEvxEwCKBtikxefCJZlmyssGiXJEVBMoXWG+W4u3rHpU9O/vL35k9yhIgoJfFxcYIBCug98bvM5PCrDfzrcdiwX4WR0egWgJ6u6irc0SOH2bymSDNCehB6nJsBEoU0Pvk2jtY//Hp3OskBJwSMOf3E2ZRl1s3u+TaZaaJDapu+c8RlCzHRaBEgVlz4/Kzf2qXbS+0EMxLNGOz8AnoKI1nX2mVJCM0Aqs8WuiB0XJgBAoLNDXXy1Zzn3zVeh3iU3hb3kXABQFdMGjbiy3y7n91u1Ac68pAQLeuSsiQ6wJ6eX2dWcp0i7m8znhy12ub8mULaEfP9WY53wPfMO97to3X5wR0r4Lsj0AZAjPN5fXHnksxDK0MMzZ1T+DBJ1Jy8eywXL8y4l7halgi7qHXEJ+Pjo5AsrFOHns+Ja/8YzvBPDrVTknzCMRMU/Lpn7RKzNxXJ/knQAvdP0uOhEBOgeVrk/KwmRyG3us5eXgxogK63O/Wbc3yxQdMOuPXKUBA90uS4yCQJaCroT32fIssWJLIeoenCCCgAnov/dSxIblwZhgQHwS45O4DIodAYKKAdnrbaBZR+dv/3kEwnwjD7whkCejfyrYXUpJIcOk9i6aipwT0itjYCYHcAlNnxOQVM6b8oadSEuefVG4kXkVggkBbRywz4mPCS/xaoQCX3CuEYzcEJgrouuT3Pthkpm1tZo3yiTD8jkAJAnrp/fuDg3LlIrPIlcCVdxNa6HlpeAOB0gR0JbRX/7lDNj9KMC9NjK0QmCygl951FEgdEWkyTJnPaKGXCcbmCIwL1Jt/PveahVTue9gEcv4RjbPwE4GKBPSLsU64xIQzFfFldiKgV27HnhEW0CE3T5rFJmbM5k8owqcBRfdZYMtjzXL80JD09436fORoHI52RTTqmVL6JKCXBjeYHuyv/Us7wdwnUw6DwLiAToW85bGm8af8LFOA5kWZYGweXYFUa32mVT5vEePKo3sWUPKgBVZvMpfddw/IjatMC1uuNS30csXYPpICS1Y1yM//W4cQzCNZ/RS6igJ6FWyrmeudVL4ALfTyzdgjQgI6lvzhp5tljWk1kBBAoDoCC5cmZM6CRGYBl+p8ohufQgvdjXqkFAEI6CQxr/5zO8E8AFsOiUAxgQfM8sKk8gRooZfnxdYREdAW+cPPNEuc1aAiUuMU0zaB2fPjMn9xQs6dYp73UuuGgF6qFNtFQkDnlNYJLlasS0aivBQSAZsF7nu4iYBeRgUR0MvAYlO3BaZMi8mzP2sV/UlCAIHaC+h99Nnz4nLpPFPCllIb3EMvRYltnBdYtrpBfmbulxPMna9qChgygU1bGZdeapXRQi9Viu2cFNApW3WIjC53SkIAAfsEFi1vkPYpMbl1k3HpxWqHFnoxId53VqA5VS8v/X0bwdzZGqZgLgjouPR19/GFu5S6JKCXosQ2zgnMMvflXvvX9sxYV+cKR4EQcExg1Yak6JwQpMICBPTCPrzroMBas6LTy79ol+YWTn8Hq5ciOSigc7xrPxdSYQH+oxX24V2HBGKm8/q2F1rksedSUk9HdodqlqJEQWD1Ri67F6tnOsUVE+J9JwRSpjX+nBmSNnMup7wTFUohIiegE820dcSkq5POcfkqnxZ6Phled0Zglgnir5rlTgnmzlQpBYmowPK1XHYvVPUE9EI6vBd6Ae1M85Nfcr889BVJARAwAsvWMINjoROB64+FdHgvtAI61OXBJxlfHtoKJOMI5BCYOj0mHWYmx87rXHbPwSO00HOp8FqoBbRH7As/Z3x5qCuRzCOQR2DxCi6756EhoOeD4fVwCrSZGaV+9k/tsmBJIpwFINcIIFBQYNEy/rbzAXHJPZ8Mr4dOQBdy0J7sjU1MQBG6yiPDCJQoMHNuQvQq3NDgWIl7RGczLrlHp66dLumq9Ul56e/aCOZO1zKFQ0BE11+Yt4hWeq5zgYCeS4XXQiOgbfEtjzfLEz9uYbKY0NQaGUXAm8CCpQT0XIJccs+lwmuhENCZ3540gZyhLKGoLjKJgG8C8xdrx7he347nyoEI6K7UZMTKoffJn3+1TXT2KBICCERLoLW9XrQDbBdLqk6qeP4bTuLgSRgEdPrHF3/eKu1TmZA9DPVFHhEIQmDewgQBPQuWe+hZIDy1W2DGnLi88o9tBHO7q4ncIRC4wNyFtEezkRHJFuG5tQILTUeYZ15plQTrIltbR2QMgWoJ6DBV0mQBWuiTPXhmqYDOyf78a20Ec0vrh2whUG2BVGu96L100h0BNO5Y8JulAvc+2CRPvGiGpXG2WlpDZAuB2gjMnkcrfaI8/yInavC7VQK6wMrDT6fkgW3NVuWLzCCAgB0CM+dx13hiTaAxUYPfrRHQ1ri2ylesY7lEayqFjCBgmcAs00mWdEcAjTsW/GaJQDxeZzq/tciiZayqZEmVkA0ErBSYOjMmOsHUCKupZuqHS+5WnqbRzZQuuvDi37YSzKN7ClByBEoWiMXqZMoM2qXjYAT0cQl+1lxAZ3976e/bhOEoNa+KUGRgbFRkeGhMxiK46FY6PSb6IIlMN6100m0BvtpwJlgh0Jyqlx+b1dKmzuCP04oKsSgTGrBvXB2R86eG5NL5tHR3jUqvefT3mYhuknaebDLnT4sZxqSzCM5ZEJd5ixPSbqYGDXvSJUIvnh2W86eHMwY93bfLPh7M9fZUqu122aeZwKarkOkX4kRDdJYQnjZTw9hg2Kval/wT0H1h5CBeBFrMPyRtmbvwD9iLA/tOFhgcGJMD3wzI4f0D0mMCeL6kAb+vZzTzuHIxLd8fuv3PXb8crr2nUVZvbJRYyP7T6ReXb3f1y6nvh2S0wP1hDey3boxkHhr09+8aMPeU62TxygbZtKVRdGZF15N+kSHdFnC/tqlpqwV0Yoif/KKdCSKsrqXqZk47OB34pl/27OgXDeqVJm3Vb3+vV/Z+2Z8Z+rhijRkxYXnDtfP6iOz8uE9Om0BeaRoZGZPj5kuNPpauapCtT6TMlQt3765OmU4YGz9XkBiX4GfVBbRFri1zbaGTEFCBy6Zl+vHbPaKBza+krfsP3+yRQ3sHZdsLKSuvBGkrfPeOvsyXmNH8FyPKJjlxZCjz5eD+R5tl0wNNTk7OpH1vmprr/3oLpmwkh3bgP6lDlRmmouhKaT/5JcE8THUWdF73fdUvb/zmlq/BfGKe9V706/92S04erbz1O/F4fv2utwv++H9uyTef94ufwXw8f3rF46tP+uTP/9ElA32VX/EYP56NPzumcdld64WAbuPZ6XieOkwwf/kXbZJq4fRzvKpLLt6X5jLzzo/6Au+xrr3i3/tDtxz51o5OVL2mk9sbv+mSyxfSJVtVuuGFM8PyhvniMN6ZsNLj2Lhf+1T+l2i9oGDj2elwnjItcxPMmwnmDtdyeUU7sHsgc5+7vL0q31o70X3yTo+cOzlc+UF82HN4eEze/s9u6er07/ZCsWzprYx3zGeOODbkrd2MbiAR0DkHqiig98x/Yu6ZE8yriG75R106l5YdH/RWPZc6hv39P3ZLd6ePN6zLLMUnb/fK9SvBt8yzs6UjAT57t/rm2fnw87kOVyQR0DkHqiSgvdm1A5wueUhCQAWGTA/2D97sDuS+cSnC2oP+/Rp9/uH9t3uhl5LPILbRWw7HvrPjtoMf5WMZ1duK/Hf142ziGAUFtBe7Dk2jN3tBpsi9uePj3oLjy6sBcsXcu95vxntXM/WaTnA7Pqx9C/nz93ulv7d2Vyj8NG9hXfQMJwHdz7OKY90loDPAvWRmgOMb9F00kX7h6qW0HDGtVBvSbtO7XHuaVyt9ZToA6gxwtU56heJL0/vdhaTD1mJm1ryoJwJ61M+AAMuv40N1OlftCEdCYKLArs+C79E+8fMK/a6d03abSWyqkW6aTmnHDtrxRUbLe/TAoHSameZcSKkWAjoB3YUz2cIyNJi5pF/8OXOzW1g1Nc/SzWsjcvZEbXuYZyPo1QIvs9JlHy/f82/N1Kw2LSajedE8uZD0amDUEwJRPwMCKL8uGPGjv2mNxDzSAfA5f0hbxoBPhNY50cfngJ/4up+/61AxnY7VtqTldmEYmy7QE/WEQNTPAJ/LX2/OqGdeaWEJVJ9dXTqcbTO1jdueOBzsDHJnzbj3ITOxjW1J7+dr3sKe9D561BMCUT8DfCy/LmP55I9bZNGyBh+PyqFcEtB7yNWcSKUcu0vnTMANsLPamePBfmEop6zZ29qct+y85nueNH12op4I6FE/A3ws/yPPpGT5WrOiFQmBPALnT9nbEtR51HV61KDS+dPVn0Sm1LKcs7heSi1DspGATkAv9Wxhu4ICm81qTuvuayy4DW8ioOt825x05rogUp8Z723rlQktb/etUdF55cOcko2EMwTCfAZbkvd19zbK/Y80WZIbsmGzwDUz/tzmpOPjg0i2l1vLHFTZg/DMdcyEGVkT9URAj/oZ4LH8S1c3yCPPpjwehd2jIKA9yW1upWod3LgWTEC/YYbq2Z50OGGYEwGdudzDfP7WPO9zFybkqZdaRTvDkRAoJqALodg0BjtXfnW98CA6xnXdtP9y9q2b4Q7o8XiuGo3Wa7TQo1XfvpV22syYPP9qq8SYBM43U9cPpHOYhyEFcS85DGUPotzVrG+d/yLqiYAe9TOggvLrvOw6C1xDkj+gCvgiu8tAfzgCehD5HOizv+wD/faNkS/nj6WexoUQ0Ms5Y9hWdGjICyaYs6Y5J0O5Aml7h2FPKorO7e53CuKYUcxjoTLX19PAIKAXOkN4b5KArmb0/GutMmUaX4UnwfCkJIFR22+g/1CKsQAa02EoehDlLunE8GmjOqIZLXSfziXnDzM+C9yc+Qnny0oBEUAgfAK0z+nlHr6ztkY53rqtWZaZIWokBCoVCMsl0boALt0GcMhKqyHvfroOQ5iT/zdKwqcR8ioMH3gYc7z2nkbZtJWJY8JYdzblORGSiztB5DMMY6TjIZ+YJQy3NYL+eySgBy0c8uMvWJpg4piQ16Et2W8MyWpYQeSzscn+f7VNIV/cJOx9APz4O7X/LPOjlByjIoGpM2Ly7E9bJeyX4ioqPDv5LpBqCce/m5ZW//OZCuCYfldQGPJYqMxjo1x09//MLSTOe6ERaE7Vywt/0yZhuFQYGtSIZ7S1I2b9rIJ63gdxzrdNsf9fbfuUcI9eGQlgdELY/mTtP8vCJupAfnXGJZ0FrqWN08OB6rSmCDqrYPtUu4PGFHNVKog0dYb985LqFbkwp9ERWuj8xw7zGRxQ3p94MSUz59r/Dyig4nPYAAVmzLb7vJoZUP5mzLK73FrlttdNsdMyHcy6OsU+1qr3CehWVUftM6PLoC5bk6x9RsiBkwKz59sd2ILKX2NznXRYfHVCr5w0mdsNYU4jZjW/qKdw12DUa8/n8i9d1SCbH2n2+agcDoE7AvMW2Tt2TW8JzFkQXP7mLQ7u2HeEK/ttvsX1UmqJwjC9bqllqXQ7Anqlco7tN21mXJ78cYsI0y05VrN2FUc7XtnaUtXlgIPoEDdeA4uW2Tsx06Ll9uZt3K/Yz/QQLXQCerGzJALvN5nxwTpHezxBNI9Adde8iHolyMa0dHWwt5r06oQubmRb0jzZfOWkVK8hAjpzuZd6sri6nY4xf/aVFmmlR7urVWxduVZuSFo3fE1b5ksDntpYl/dcsS7YLw2VVPbK9UlxYenRoUFa6LTQK/kLcGifh59OBXrf0CEqiuKTgF52X7zCrla6Tm/cUIWpTzdsbrJqoib9Qq95ciER0FmcxYXzuOIyrNqYlHX3NVa8PzsiUKnA5seaxZblLpPJOrnnweoEtbaOelm90Z6/uTXmi0xruxvtusEBWuhu1GSl/1UivN/MOXF57FnTCY6EQA0Epk6PyXpLvkxuebxZGqs4j/mWx5uq+nn5qleHqW0xX6xcSYP9TBVHQHflbC6jHNoJ7tmftUrM7iHBZZSITcMooIG01tONamewtfdWt8WsC7U8+lztv0w//nzKyk56lZ7LA/200AnolZ49Id1PL3M+/XKLBLEARUhJyHaNBBJmVMUzP20xXyxr0/Nb521/6qWWmnTQW2Y64K3ZVN0vEhOref39jdb1Y5iYv0p+7++jhU5Ar+TMCfE+D5hWkQtDVEJcBWR9gsB0MyXq4z9KTXilOr/qJDJ6laq5hivAPfJsSmbNq/5lMh1v/9BT1TcPumb7+2ihE9CDPsssOr72LL5na3U6/1hUbLJiucBKM5Rr67bq3cvVnt1Pv9wqs2sQTCdWhX6p+JFZBKmai6LofO3PmS8yri2JPGzGoKeHCegE9Il/YQ7/3maGCmVmgnO4jBQtvALay3zbC+byuwlyQSbt/Pbi37bJkpV2DJtrNP1ZXv5luyxYEvy0sPqF/qVftDl133z8XOnr4XK7WlT/es94DfCzagK6HOpzZvKYBjM8h4SArQKrzTBKHX3xyds9cuWi/0tnaUB77LlUTS+z57LXmdpe+HmbHPhmQHZ92id+z0muf/cPPtEsOkTN1dRLQM9ULQHd1TN8QrkefqZZdK52EgK2C+jl51f+qV2Ofjsou7b3SW+395aXHnPrEylZuDT4VnClvnXmu/aGzY2i0+Lu+qxPjh4YlDGPV5D1srqOeb//0SbRDoAuJz/OExd8+C/vQi0WKINONVnL3rQFssZbCOQU0OCmkx4tW9sgR/YPymHzuHa5vBa7HkNXTlt7T9JM6WrfVLM5C25eTLXWyxMvtsimB5rkW9NiP35oUMqdAU1b/MvXJmWD6cmuy6JGIfX48MXPBae6X//qvMfvgS4wuFkGXdXq1X9pD3QFKTflKJVtAt23RuXC6WG5fCEtvT0j0tczJn29ozJkZgdLmvvi2ltdW6EtZk2COWbN9blmfLnOtxD2NDoicvnisCl7Wjqvp02ZTbnN5WUtuyYt8+2y18mU6bfLrbctXOv0VqweP3u3Vw7uGSi2mfPv00J3tIp1bO8zP20lmDtav1Erlk5Pqq12fUQp6aIpc+YnMo8olbvcsvbcMt98SKy25uo58NBTet88GpfbXK1DyoUAAqUJdJkrOCQWZ3HyHNAhOeuqPJ2lk5AUCgEErBfQzoN6S4ZEQHfuHNB7iDqel4QAAghEQUCHrI2k6QqmdR3+XiNROGNLLKP27NW5qbWXKwkBBBCIgkDXDe6fj9czAX1cwoGfOtuWDtUhIYAAAlER6LxJQB+vawL6uETIf+pQlc2PVm8+7JBzkX0EEHBEoJMW+l9rkoD+V4rw/qLLUOql9qiNPQ1vjZFzBBDwS6DzOi30cUsC+rhEiH8+aIaoRWVGqBBXE1lHAIEABG5eI6CPsxLQxyVC+nPhsgYzvaW7iy6EtFrINgIIVEFAl03t6WLI2jg1AX1cIoQ/dSnIbS+kQphzsowAAgh4F7hxldb5REUC+kSNkP3+6HMtzq+iFLIqIbsIIFBFgetXy1u0p4pZq8lHEdBrwu79Q5etbhB9kBBAAIGoCly/Qgt9Yt0T0CdqhOT3JrPCkrbOSQgggECUBa6Xuayu61YE9BDW8GPPpUTvn5MQQACBqAroHO7XuYc+qfoJ6JM47H+il9l18RUSAgggEGWBm2b8eXqYOdwnngME9Ikalv/e2Fwnjz7LpXbLq4nsIYBAFQSuXqRDXDYzAT1bxOLnjzxtLrWboE5CAAEEoi5AQL/7DCCg321i5Ss6gczytUkr80amEEAAgWoLXKGFfhc5Af0uEvteSDTUiXaEIyGAAAIIiKTN+ufXr3DJPftcIKBni1j4/IHHm6WljaqysGrIEgII1EBAL7ePMuPrXfJEibtI7HpBl0Vddx9ztdtVK+QGAQRqKXDpPK3zXP4E9Fwqlrymy6E+9nxK6ugHZ0mNkA0EELBB4NI5AnqueiCg51Kx5LV19zfK9FlxS3JDNhBAAIHaC+iEMpfODdc+IxbmgIBuYaVollKt9bLl0WZLc0e2EEAAgdoIaGe4oUEmlMmlT0DPpWLBaw89lRLt3U5CAAEEELgjcOEMl9vvaEz+jYA+2cOKZ/MWJ1hJzYqaIBMIIGCbwIUzXG7PVycE9HwyNXq9Piby6DOMOa8RPx+LAAIWC+hQtYtnCej5qoiAnk+mRq9vuL9JOqaZqE5CAAEEEJgkoOPPuX8+iWTSEwL6JI7aPmk265zf/0hTbTPBpyOAAAKWCpw7Reu8UNUQ0AvpVPm9B7Y10xGuyuZ8HAIIhEfg7Mmh8GS2BjkloNcAPddHzpgdl5XrWXwllw2vIYAAAoMDY8IKa4XPAwJ6YZ+qvfuwWRqVGeGqxs0HIYBAyAT0cjvztxeuNAJ6YZ+qvLt0dYPMns+McFXB5kMQQCCUAmdPcLm9WMUR0IsJBfx+zHRo32runZMQQAABBPILnD1Jh7j8OrffIaAXEwr4fV1Jra2DYWoBM3N4BBAIscC1y2np62G91GJVSEAvJhTg+8nGOrnvYVrnARJzaAQQcEDg9HFa56VUIwG9FKWAtrn3wSbRoE5CAAEEEMgvcPp77p/n17nzDgH9jkVVf9PV1Nab5VFJCCCAAAL5BXq7R+WamSGOVFyAgF7cKJAtNpulUWNxWueB4HJQBBBwRuCUaZ2zWGpp1UlAL83J1606psZkFZPI+GrKwRBAwE2Bk0e53F5qzRLQS5XycTttndch76Moh0IAARcFBvrH5CLLpZZctYSVkqn82XDazJjoRDIkBBBAAIHCAqdM65zZ4QobTXyXgD5Rowq/Z1rn3DqvgjQfgQACYRc4fngw7EWoav4J6FXknjEnLotX0DqvIjkfhQACIRXo7xuVC1xuL6v2COhlcXnbeIu5d05CAAEEECgucPwwl9uLK03egoA+2SOwZ7PmxWXB0kRgx+fACCCAgEsC33/H5fZy65OAXq5YhdtvfoTWeYV07IYAAhETuHVzRC5fYDKZcqudgF6uWAXbz5obl/lLaJ1XQMcuCCAQQYFjtM4rqnUCekVs5e10H63z8sDYGgEEIiswZqaFO3qAy+2VnAAE9ErUythnxuy4LOTeeRlibIoAAlEW0J7t3bdYKrWSc4CAXolaGfvc+1BTGVuzKQIIIBBtgSPf0jqv9AwgoFcqV8J+HdNijDsvwYlNEEAAARUYHBiTk0eYu73Ss4GAXqlcCfvds7VJ6pgVrgQpNkEAAQREtDNcOs3aapWeCwT0SuWK7Kfrna9YmyyyFW8jgAACCIwLHNw7MP4rPysQIKBXgFbKLhs2N0p9rJQt2QYBBBBA4OLZYbl5bQQIDwIEdA94+XZtSNbJmk2N+d7mdQQQQACBLIGDe+gMl0VS9lMCetlkxXdYvTEpGtRJCCCAAALFBfp6R+XEUQJ6canCWxDQC/uU/W6dEV1/P0PVyoZjBwQQiKzAwT0DMsrVds/1T0D3TDj5AEvM8qit7bBOVuEZAgggkFtgxATyQ3tpnefWKe9VIk95XkW3Xn8/986LIrEBAggg8IPA8UODopfcSd4FCOjeDf96hGkz4zJnAYuw/BWEXxBAAIEiAvt39RfZgrdLFSCglypVwnbr76N1XgITmyCAAAIZgfOnh+X6FW6e+3U6ENB9kkw21snytQ0+HY3DIIAAAu4L7PuS1rmftUxA90lz5fqkxBMMVfOJk8MggIDjAtoyP3ty2PFSVrd4BHSfvNfcw+V2nyg5DAIIREBgL61z32uZgO4DqXaEm2JWViMhgAACCBQX6Oo0E8kcZqhacanytiCgl+eVc+vVm1iEJScMLyKAAAI5BPbu7JdRRqrlkPH2EgHdm19mitelq+gM55GR3RFAICICvd2jcvQAq6oFUd0EdI+qy80SqfE4neE8MrI7AghEREBb5zo7HMl/AQK6R9NVG7jc7pGQ3RFAICICvT2jcmg/986Dqm4CugdZ7Qg3c07cwxHYFQEEEIiOwN4dpnWeHotOgatcUgK6B3Ade05CAAEEECgu0NNlWuf7uHdeXKryLQjoFdrVmdvmev+chAACCCBQXGC3ts65d14cysMWBPQK8XTseUsbfBXysRsCCERIoOvmiBzZT+s86ConIlUozLztFcKxGwIIRE5g13bGnVej0gnoFSjXG7WlK7ncXgEduyCAQMQErl9Ji655TgpegIBegfH8JQlJNjH2vAI6dkEAgYgJfPlJn4zRsb0qtU5Ar4B52Wpa5xWwsQsCCERMQNc7P3uCFdWqVe0E9DKl680aLIuWM9VrmWxsjgACERPQVvnOj/oiVuraFpeAXqb/vEXmcnsjl9vLZGNzBBCImMCxg4Ny7XI6YqWubXEJ6GX6L1lJ67xMMjZHAIGICaSHx+Qrc++cVF0BAnoZ3jqZzGIut5chxqYIIBBFgX1fDYiuqkaqrgABvQzvmXPj0pSCrAwyNkUAgYgJ9JhAvvfL/oiV2o7iEp3KqAda52VgsSkCCERSQDvC6SV3UvUFCOhlmNO7vQwsNkUAgcgJ6DA1JpGpXbUT0Eu0b22vlynTzZg1EgIIIIDAXQK68Mr293rvep0XqidAQC/ReuEyereXSMVmCCAQQQG9b955neXUaln1BPQS9RcsTZS4JZshgAAC0RLovDEie8zyqKTaChDQS/CPmSvtcxcS0EugYhMEEIiYgM4I9+nbvTKSpiNcrauegF5CDcyal5BEgtnhSqBiEwQQiJjAwT0DcvEc87XbUO0E9BJqQad7JSGAAAIITBbo6hyRLz9mRrjJKrV7RkAvwZ7L7SUgsQkCCERKQC+1f/xWrwwz5tyaeiegF6mKuLnUPnNOvMhWvI0AAghES2D/rn65eJZL7TbVOgG9SG3MMtO96pKpJAQQQACB2wI3ro7Irk+51G7b+UBAL1Ijs+fTOi9CxNsIIBAhAe3N/sGb3aITyZDsEiCgF6kP7eFOQgABBBC4LbDDzNWuLXSSfQIE9AJ1osulcv+8ABBvIYBApAROHRuS73YPRKrMYSosAb1AbbVPiUmykfHnBYh4CwEEIiLQfWvU9GrviUhpw1lMAnqBeptB7/YCOryFAAJRERg1V9jf/2O3DA4wG5zNdU5AL1A702fRIa4AD28hgEBEBHZ81CtXLqQjUtrwFpOAXqDups9ivFoBHt5CAIEICHx/aFAOfMN98zBUNQG9QC1Nm0kLvQAPbxUQ6OsZlTQzaBUQqv1bukIYqbCA9mbXhVdI4RAgoOepp1RrPR3i8tjwcnGB7w8Nic4ySLJTQMdQn/5+yM7MWZIrvV/+l993M7WrJfVRSjYI6HmUpk7ncnseGl4uInD0wKAJ5kU24u2aCuz7sl+aU/z7y1cJOk/7B6YTnC6+QgqPAGd0nrqaQkDPI8PLhQT0UvuOD3tl8YqGQpvxXg0Fbt0ckT07+mWmmdaZlFtgp+kEd/Yk87Tn1rH3VQJ6nrrpmEoLPQ8NLxcQ+OSdXmnriNH6K2BU67c+NXVUb/7z6TwTpLsFDu0bkP276AR3t4z9rxDQ89RROwE9jwwv5xM4vH9QzhwfkgVLuN6ez6jWrx/cMyAXzgxLB1fgclaFtsq3v0snuJw4IXiRgJ6nkvj2ngeGl3MK6CxaOz64/Y9w3mICek6kGr/Y1TkqOz++vUIYf993V8bVS2l57w/dMjp693u8Eg4BAnqOeorF66S5BZocNLyUQ0A7EH30px4ZGhoTPXdmziWg52Cq6UtaRx//uUeGTR1pamnj73tihegQvrd/Z3q0/+Az8T1+D48AZ3WOumo1f+y6MAsJgVIE9u7sl4vnbncgmjE7JjFuzZbCVtVtJtaRfnBTM//6xitAry79+T+6pL+Ppvm4SVh/clbnqDm+vedA4aWcAlcvpuXr7bcv4+oGtM5zMtX0RZ2ydGIdaWZYdOl2lfR2j8qf/l+X9HQRzGt6kvr04QT0HJApLsflUOGlbAG9PPnBmz2T7jnOYLrgbKaaPh8a1Dq6+74wk/6IaDB/8/92Mda8pmeovx/OQMwcninun+dQ4aVsge3v9YqOaZ6YpjJd8ESOmv+uy31qZ7jspMPWopy0Rf6maZl3ZZ2/UTZxoewE9By1SEDPgcJLkwSOfTcoOiPcxKRBooOxzRNJavr7/l39cvJo7uldo9yTW4P4n8w9c713TnJLgICeoz6bmBIyhwovjQvcMj2CP8sxVrelPSb1dIgbZ6rpTx1r/uUPQ9RyZUQvxUcx6WIr2gGur5dg7mL9E9Bz1Co9YHOg8FJGYCQ9Ju+9cWf400SWtvaIX8ediFHD3/Vy8vumjgq1wqMY0C6dS8s7r3eJLrpCclOAgJ6jXhubGLOWg4WXjMDnH/TJ9SvpnBaMjsjJUtUX0+YLl64QVmwIVtQWHdFbDx+aDpzqQ3JXgICeo24Z0pIDhZdE75sf2pt/jmtu1dT4JDGxSiePuXY59xeuibm7aS49RyUd+GZAvjCzGOrkOiS3BQjoOeq3oZFLpzlYIv2S3nv89C+F57jmVk1tT5FdZj6A44dzd4LLzpleZdHbJzqzn6tJA7gGcg3opGgIELmy6lln+WKmryyUiD/VDlTvmjmu08OFmzgNSXeDg+2nwJFvB2X3F/0lZ3PENNAvnS/eki/5gJZtqHMkvPN6N8HcsnoJOjsE9CzhRAP/lLNIIv/0I3MZV3u2F0uJBOdOMaMg3j93alg+faen7EOfOeHmet86HO2N39zKrPxXNgo7hFqAgJ5VfcwglQUS8ae7d/TLqWOlXcaNcQOr6mfL9Ssj8t5/3T0TXCkZOXHYzCNQ+KJLKYexaptT3w/J6//WaTpuFv8CalXGyYwvAvwLymKMO3xPLauoPC0ioC24rz+7M097kc1Z0KcYkM/va0/1t37XlVnlrpJD6/C2M2b974VLw786nt4O2vlRn3xn1nsnRVeAgJ5V90wMkgUS0ad6if1DMwd4OT2Dy9k2oqy+FbuvR1cI6xb96SXt/rzPBPR2L4eo+b46ic6n79w9DXHNM0YGqi5AQM8ir49xHzSLJHJPtRPcO2Ysc7kTcKTd7WNl1TnQ3zeWmbrUj7Hkl81KbDqF78r1SavKWEpmBsxypzvNbHhHTYdAx+4clFJ8tskhQEDPQon6og1ZHJF7qq1sXUGt83r59yCHBry1FiOHXUGBB/rHTMv8lty8Vn795Ps4Hdo1d2FCwjIxkM6Ad9BcWtclYcv90pnPgNfdECCgZ9VjPQ30LJFoPf3qk76Kewdry5EUnIDO/qZrd+ucAH4mDYrvmo51L/9Dm9jeh+aUmfHty0/7KvrC6acZx7JTgIBuZ72QqxoI6KXXvV+WPpY5O4vayYoUjECv3jM3wfxmBVdOSsnR1UvpzNSoz77SamXnxvOnh2WXCeR6i4CEQD4BAnqWTKEFHbI25alDArpwRSVjmScSZK+NPvE9fq9cQNcz18vsudY1r/yod++p851/8MduefKlVmsmlzpvxth/80WfXDxLIL+7xnglW4CAniWiM0iRoiWggfgvv+8Sr3Xv533daNVA/tLqFK1v/db0Zq/Scp86dWznjVvyxIspmT6rNv8etR/HaTOefM/OfrlCizz/ycE7dwnU5oy9Kxv2vFBsek97ckpO/BDQ+95v/65btLOV16T3eHu7RyXVynxNXi11f73MrPe2q712uX6J+K//fUtWbkjK5keaq1afOlRSb/scNYsAcfvGjzMoescgoGfV+aAZskSKhoB+eXvnP7vEz0vl2qJasqohGoABllID2ydmOtfRGl0x01tvh/cNyjGTj2VrkrJhc6PvLXb9jMvnh00nTPM4MeR7Z78Aq4dDWypAQM+qGB16pJe86ujtniXj1lP9Z6oLrly56O+9yQtnhwnoXk4V87enq6aVs9CKl48rtq/ehsm0mk1gb58SkzkL45khbnMXJMpuueuCKdr5Ts+5i+Y8uWTuiw+Z10gI+CVAQM+S1H/0OoylsYmInkXjzFP9wvbRn3rkbACLc+hCIaTKBPSKiS6Ec+JIaXPnV/Yple+lV3L0oS13TbpcbmNznflfUS/JRv1ZZ37WS9osyzpobuEMmMaB/hw0P/WWTrVvHVReUvYMqwABPUfN6RCZxiazjirJSYHt7/bK94du/1P2u4A6IY3+09fWHKl0AV0hTO+XX7vs7xWT0nNQ/pbaZ6I/M9V/je4LlJ9l9nBcgN47OSq4p4s/0BwsTry0wyxgcXBvsAtY6PAnUukC2vnt96YTWpiCeemlY0sEqidAQM9h3W3GvZLcE9CJOfZ/VfnEMaWKHDO9lEmlCew1Q7P+/Nsu0XnJSQgg4E2AS+45/Pzs9Zzj8LxUAwGd91rXNq9G0qlJL54bljnzw78sZ1Be2k/l47d6Sl5rPqh8cFwEXBKghZ6jNitZmCPHYXjJEoGvt/fLN59XJ5iPF1lbnqTcAnpp/ff/3kkwz83DqwhULEALPQfddZ8Xf8jxEbxUJQG9zF6tlvnEIunYYh2aNMcMbyLdETjwzYBZ8rNXRsLT9+1O5vkNAcsFaKHnqKB+M81ktaaazPHxvOSTwE7TAa4WwXw8+1980Cdj3BrOcOgMem/9rks+f59gPn5+8BMBvwUI6HlEr/o84Uiej+HlAAR0nPlnZmjavip0gCuUfb20vG9XxC+9m7o4ZEYV/PZ/dQYy7r+QP+8hEDUBLrnnqXFdpnDRcqbwzMNj7cs6MZB2trKlp/nXn/XL/MUJ36cNtbYCJmRM50TXL1aXz3N9fQILvyIQmAAt9Dy0l81ymqRwCegMXTo5iS3BXPVGRsbk/Td6IjVLmC5489lfeuX1f79FMA/XnxC5DbkALfQ8FXjZXHIfMQEiFmcK2DxEVr2sw6Deeb1LdF1z25IOg3zfrLP9wmttUufwV2iduvXbrwdk75f9kfoCY9v5Rn6iK0BAz1P3GswvmUuF8xbRSzkPkTUvj3e40vHftiadN/7zD3rl0WdTtmax4nzpAiZ6n3yPGedPZ9KKGdkRAc8CBPQChOdODhPQC/jY8JYGce09rUHd9vTd7gFJNNTJ1m3Ntme1pPzp0LPD+2+3yFm/uyQyNkIgUAECegHeM8eHZOsTbvzzLVDM0L6lc4DrPfMwrWKlE85o8Nv2o5TEE+G8naPLgB7cMyD7zeX1PrOQEQkBBOwQIKAXqIcb10aky8zr3tbh8I3PAuW3+a0j3w7Kp+/0iPZqD1v6/uCgXDPrYj/xYovMmheeP0G9CnLAXGXQy+vaZ4GEAAJ2CYTnv0mN3E4eHZRNDzTV6NP52FwCX5nZ3/R+bZhT540ReeM3t2T1xqRsebw5s7a2reW5YjqIHjCt8eNHBmXU3m4KtvKRLwSqJkBAL0J98sgQAb2IUbXe1mDy8dv2jDH3Wm6dAOfQvkE5fmhINmxplI1bmqQhacdleL2UrlcSjpqV465fIYp7rWv2R6AaAgT0Iso6wYy2pjqmxopsydtBCujY5vf+0J2ZHz3Iz6nFsYfMPWldPEbnOV97b6NsuL9RmlLVv82jgVv7jZw2jyvmvNcvHCQEEAiPAAG9hLrSDkAPP+3ecKMSim7FJlfN/Wbt/OZ6T2q9L623EvaZcdy6qMviFQ2ZR0tbMMFdv6hePDMsF86k5YJZSIYOblac7mQCgYoF6n79q/N8Dy/Cp0ONfvk/pkhjkx2XQ4tk16m3vzNfpnaY8ds61jmqqa0jJrPmxmWmeUydEZOOaTFpLrEF3983munY2dVpOnje1N+1o+eI3LoxKvoeCQEE3BGghV5CXeowHZ396kGGsJWg5c8m2lr9xNwvP3l0yJ8Dhvgo40H4mLmnPZ7qTaNdv2g2mEfC3HfX32OxOtFzVYfxDZrH0OAondjGwfiJQAQECOglVrLe31x3T6O0MoStRLHKN9MJfbTzWxgmi6m8lN721OF6+qWH4WPeHNkbAZcEgrk555LQD2XRqWC3m7WcScEJaOtSF/V467fhmPktOAmOjAACCJQvQAu9DDPtAawrea1YlyxjLzYtRUB7Vm83S2263vGtFAu2QQABBCoRIKCXqbb9vV6ZPT8hre1c3CiTLufmeln9C9Pp7YQZ709CAAEEEKhcgKhUpp12OHr/je5I97oukyzn5jpJjHY0/I//2UkwzynEiwgggEB5ArTQy/PKbK1TYW5/t0e2vdBSwd7scvr7IdnxYZ/oOuEkBBBAAAF/BAjoFToe3j8o7Wb2uHu2Ms97qYTXLqdl50d9oqukkRBAAAEE/BUgoHvw/OqTPkm11NNJrohht1mxbtf2vszc4EwnWgSLtxFAAIEKBQjoFcLpbhqcPn6rJ7Ou9ZKVDR6O5OauOpXobjOV6eF9A/Q5cLOKKRUCCFgkQED3WBk6wcf7f+yW537WKouWEdSVs793NNPh7eCeQUmb8fskBBBAAIHgBQjoPhhrj+33zOIhT/64VZatiW5Q7zUtcl1Y5NBeArkPpxWHQAABBMoSIKCXxZV/Y1085IM3u+XyhUbZui0lsQjJ6lzj+74ckCMHBkVn1CMhgAACCFRfIEJhJ3hcvaf+7dcDcubEsDxilltdsDQR/IfW8BMunUub8vbLqWNDorceSAgggAACtRMgoAdgf8usM/3W77pk3uKEbHm0WWbNc4dZL6vr9LdHTWv85jXGkQdw+nBIBBBAoCIBdyJNRcUPdqfzp4bl/KlbMndhQjZuaZSFptNcXQiXVNf51XUZU31cOjec6d0frBxHRwABBBAoV4CAXq5YBdtfODMs+mibEpM1G5OyakNSmlL2zrqrl881cJ81y5iePTEk16/QEq+g2tkFAQQQqKpA3a9/dZ5eTFUlF6k3sXzB0gZZaVZtW7g8IfF4bZvteu9fZ3G7YGZwO2++eOi9cV3KlIQAAgggEB4BWug1qCttAet85vqImWA+fVZMZs2Nm0dCZpqfLW3Btd7Tw2Nyw9z7vmFa3devpjOt7+tX0qKLzpAQQAABBMIrQECvcd3pMK/L59OZh8hAJjfJxjrpmBaTDjNXfKq1Xhoa6qQhWScJ82hI3nmur9XHJNOaHjYBeci0qvUx/vv4T52xrctMv6rDy/R3pl+tcaXz8QgggEAAAgT0AFC9HnJwYGKQ93o09kcAAQQQiIJAcNd2o6BHGRFAAAEEELBEgIBuSUWQDQQQQAABBLwIENC96LEvAggggAAClggQ0C2pCLKBAAIIIICAFwECuhc99kUAAQQQQMASAQK6JRVBNhBAAAEEEPAiQED3ose+CCCAAAIIWCJAQLekIsgGAggggAACXgQI6F702BcBBBBAAAFLBAjollQE2UAAAQQQQMCLAAHdix77IoAAAgggYIkAAd2SiiAbCCCAAAIIeBEgoHvRY18EEEAAAQQsESCgW1IRZAMBBBBAAAEvAgR0L3rsiwACCCCAgCUCBHRLKoJsIIAAAggg4EWAgO5Fj30RQAABBBCwRICAbklFkA0EEEAAAQS8CBDQveixLwIIIIAAApYIENAtqQiygQACCCCAgBcBAroXPfZFAAEEEEDAEgECuiUVQTYQQAABBBDwIkBA96LHvggggAACCFgiQEC3pCLIBgIIIIAAAl4ECOhe9NgXAQQQQAABSwQI6JZUBNlAAAEEEEDAiwAB3Yse+yKAAAIIIGCJAAHdkoogGwgggAACCHgRIKB70WNfBBBAAAEELBEgoFtSEWQDAQQQQAABLwIEdC967IsAAggggIAlAgR0SyqCbCCAAAIIIOBFgIDuRY99EUAAAQQQsESAgG5JRZANBBBAAAEEvAgQ0L3osS8CCCCAAAKWCBDQLakIsoEAAggggIAXAQK6Fz32RQABBBBAwBIBArolFUE2EEAAAQQQ8CJAQPeix74IIIAAAghYIkBAt6QiyAYCCCCAAAJeBAjoXvTYFwEEEEAAAUsECOiWVATZQAABBBBAwIsAAd2LHvsigAACCCBgiQAB3ZKKIBsIIIAAAgh4ESCge9FjXwQQQAABBCwRIKBbUhFkAwEEEEAAAS8CBHQveuyLAAIIIICAJQIEdEsqgmwggAACCCDgRYCA7kWPfRFAAAEEELBEgIBuSUWQDQQQQAABBLwIENC96LEvAggggAAClggQ0C2pCLKBAAIIIICAFwECuhc99kUAAQQQQMASAQK6JRVBNhBAAAEEEPAiQED3ose+CCCAAAIIWCJAQLekaw8AKAAAAqRJREFUIsgGAggggAACXgQI6F702BcBBBBAAAFLBAjollQE2UAAAQQQQMCLAAHdix77IoAAAgggYIkAAd2SiiAbCCCAAAIIeBEgoHvRY18EEEAAAQQsESCgW1IRZAMBBBBAAAEvAgR0L3rsiwACCCCAgCUCBHRLKoJsIIAAAggg4EWAgO5Fj30RQAABBBCwRICAbklFkA0EEEAAAQS8CBDQveixLwIIIIAAApYIENAtqQiygQACCCCAgBcBAroXPfZFAAEEEEDAEgECuiUVQTYQQAABBBDwIkBA96LHvggggAACCFgiQEC3pCLIBgIIIIAAAl4ECOhe9NgXAQQQQAABSwQI6JZUBNlAAAEEEEDAiwAB3Yse+yKAAAIIIGCJAAHdkoogGwgggAACCHgRIKB70WNfBBBAAAEELBEgoFtSEWQDAQQQQAABLwIEdC967IsAAggggIAlAgR0SyqCbCCAAAIIIOBFgIDuRY99EUAAAQQQsESAgG5JRZANBBBAAAEEvAgQ0L3osS8CCCCAAAKWCBDQLakIsoEAAggggIAXAQK6Fz32RQABBBBAwBIBArolFUE2EEAAAQQQ8CJAQPeix74IIIAAAghYIkBAt6QiyAYCCCCAAAJeBAjoXvTYFwEEEEAAAUsECOiWVATZQAABBBBAwIsAAd2LHvsigAACCCBgiQAB3ZKKIBsIIIAAAgh4ESCge9FjXwQQQAABBCwRIKBbUhFkAwEEEEAAAS8CBHQveuyLAAIIIICAJQIEdEsqgmwggAACCCDgRYCA7kWPfRFAAAEEELBEgIBuSUWQDQQQQAABBLwIENC96LEvAggggAAClggQ0C2pCLKBAAIIIICAFwECuhc99kUAAQQQQMASAQK6JRVBNhBAAAEEEPAi8P8B2gURR7oisIAAAAAASUVORK5CYII="; const PhantomExtension = createAdapterExtension({ phantom: { id: "phantom", enabled: false, walletName: "Phantom", logo: phantomLogo, website: "https://phantom.app", chain: "SOL", adapter: PhantomAdapter, config: { enabled: false, solanaNetwork: WalletAdapterNetwork.Mainnet, // Provider canister ID should be set by the user siwsProviderCanisterId: "" } } }); export { PhantomAdapter, PhantomExtension, formatSiwsMessage2 as formatSiwsMessage };