diff --git a/.gitignore b/.gitignore index 286b1e0..3e5cc04 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ core/target/ extension/node_modules/ +extension/dist/ extension/web-ext-artifacts/ tests/storage/dual-signatures/ diff --git a/PRIVACY_POLICY.md b/PRIVACY_POLICY.md new file mode 100644 index 0000000..ad72e8e --- /dev/null +++ b/PRIVACY_POLICY.md @@ -0,0 +1,142 @@ +# Contractless Web3 Wallet Privacy Policy + +Effective date: August 2, 2026 + +Contractless Web3 Wallet is a browser extension for creating and managing +Contractless blockchain wallets, connecting to compatible Web3 applications, +and reviewing, signing, and broadcasting Contractless transactions. + +## Information Contractless Does Not Collect + +Contractless Web3 Wallet does not include advertising, analytics, telemetry, +tracking, or behavioral profiling. The developer does not collect or sell: + +- names, email addresses, telephone numbers, or other identifying information; +- browsing history or general website activity; +- health information; +- personal communications; +- precise or approximate location information; or +- wallet encryption keys or private keys. + +## Information Processed Locally + +The wallet must process financial and authentication information to provide its +requested functionality. This processing occurs locally inside the browser +extension and does not make the information available to the developer. + +Locally processed information may include: + +- encrypted Contractless wallet files; +- wallet addresses, public keys, and vanity addresses; +- private keys and wallet encryption keys while the wallet is unlocked; +- balances, assets, NFTs, RWAs, loans, and transaction history; +- unsigned and signed Contractless transactions; +- website connection approvals and temporary application access keys; and +- wallet labels, network selection, API endpoints, and automatic-lock settings. + +Private keys are encrypted before being placed in persistent extension storage. +Decrypted private keys exist only while the wallet is unlocked. Locking the +wallet clears decrypted wallet material and expires active website sessions. + +## Contractless API Communication + +The extension communicates with the Contractless API selected in the wallet's +settings. Testnet defaults to `https://api.contractless.dev`. Users may replace +the API endpoint, and mainnet uses a separately configured endpoint. + +The extension sends only the information required to perform a user-requested +blockchain operation. Depending on the request, this may include: + +- a wallet address, public key, and authentication signature; +- an address, asset identifier, transaction identifier, or block identifier + required for a blockchain lookup; or +- a complete signed transaction submitted for validation and broadcast. + +Private keys and wallet encryption keys are never sent to a Contractless API, +website, blockchain node, or the extension developer. + +An API endpoint chosen by the user is operated independently and may have its +own privacy and logging practices. Users should only configure API endpoints +they trust. + +## Website Connections + +Contractless-compatible websites may request access to the wallet through the +Contractless Web3 provider. A website does not receive the active wallet address +until the user explicitly approves its connection request. + +After approval, the website receives a temporary access key associated with +that website, application identifier, wallet, and unlock session. The access +expires when the wallet locks or the user disconnects the application. + +Websites may request message signatures or transactions. The wallet displays +the request for review and requires user approval before signing. A connected +website receives only the address, signatures, transaction information, and +other results required to complete the approved request. Websites never receive +the wallet private key or encryption key. + +Contractless does not control third-party websites. Their handling of +information received after user approval is governed by their own privacy +policies. + +## Browser Permissions + +Contractless Web3 Wallet uses the following browser permissions: + +- **Storage:** Stores encrypted wallets, wallet settings, labels, and temporary + application sessions. +- **Alarms:** Enforces the user-configured automatic wallet lock timeout. +- **Clipboard write:** Copies information only after the user selects a copy + action, such as copying an address or transaction identifier. +- **Host access:** Makes the Contractless provider available to compatible + websites and communicates with the configured Contractless API. The extension + does not read or collect general webpage content. + +## Data Retention and Deletion + +Wallet information remains in browser extension storage until the user removes +it, clears the extension's storage, or uninstalls the extension. Temporary +website access information expires when the wallet locks or the application is +disconnected. + +Contractless does not maintain a separate developer-controlled database of +extension wallets or user activity. + +## Sharing and Sale of Information + +Contractless does not sell user information. Information is not used for +advertising, credit decisions, behavioral profiling, or purposes unrelated to +the wallet's user-facing functionality. + +Information is transmitted only when necessary to complete a user-requested +wallet operation, communicate with the configured Contractless API, or respond +to an explicitly approved website request. + +The use of information by Contractless Web3 Wallet is limited to providing and +improving its disclosed wallet functionality. Information is not transferred +for advertising or other unrelated purposes, and humans are not permitted to +read private wallet information except when specifically requested by the user +for support, required for security, or required by law. + +## Security + +Contractless Web3 Wallet performs cryptographic operations locally using code +and WebAssembly bundled with the extension. API communication must use HTTPS, +except when a user deliberately configures a local development endpoint. + +No system can guarantee absolute security. Users are responsible for protecting +their wallet images, private keys, encryption keys, devices, and configured API +endpoints. + +## Changes to This Policy + +This policy may be updated when wallet functionality or privacy requirements +change. Material changes will be reflected by updating this document and its +effective date. + +## Contact + +Questions or privacy concerns may be submitted through the Contractless Web3 +Wallet repository: + +https://contractless.dev/contractless/Contractless-Web3-Wallets diff --git a/README.md b/README.md index 715c1b6..f76d95c 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,9 @@ Private keys remain inside the extension. Websites receive only approved addresses, signatures, signed transaction bytes, and session-scoped access keys. +The wallet's data-handling practices are described in the +[Privacy Policy](PRIVACY_POLICY.md). + ## Integration Test The `tests/tests.html` page verifies that a website can detect the extension, diff --git a/extension/dist/assets/contractless-logo-BgfMS-Kf.png b/extension/dist/assets/contractless-logo-BgfMS-Kf.png deleted file mode 100644 index 729e4d7..0000000 Binary files a/extension/dist/assets/contractless-logo-BgfMS-Kf.png and /dev/null differ diff --git a/extension/dist/assets/contractless_browser_core_bg-C_vtp2Os.wasm b/extension/dist/assets/contractless_browser_core_bg-C_vtp2Os.wasm deleted file mode 100644 index 7264d84..0000000 Binary files a/extension/dist/assets/contractless_browser_core_bg-C_vtp2Os.wasm and /dev/null differ diff --git a/extension/dist/assets/popup-C5oUQoSX.css b/extension/dist/assets/popup-C5oUQoSX.css deleted file mode 100644 index e5133e2..0000000 --- a/extension/dist/assets/popup-C5oUQoSX.css +++ /dev/null @@ -1 +0,0 @@ -:root{--blue: #2167a5;--blue-deep: #174d7c;--ink: #13202a;--muted-white: rgb(255 255 255 / 90%);--danger: #b9382e;--danger-soft: #fff0ee;--success: #1d8054;--dark: #0c151d;--surface: #111e28;--surface-raised: #172936;--surface-active: #1b3547;--dark-line: #314957;--dark-muted: #c4d0d7;--accent: #55c5dc;font:14px/1.45 Arial,Helvetica,sans-serif}*{box-sizing:border-box}body{width:390px;min-width:390px;min-height:600px;margin:0;background:var(--blue);color:#fff}button,input,textarea,select{font:inherit}button{cursor:pointer}button:disabled{cursor:not-allowed}.wallet-shell{position:relative;width:390px;height:600px;overflow:hidden;background:var(--blue)}.screen{width:100%;height:100%;background:var(--blue)}.screen[hidden]{display:none}.wallet-header{height:72px;display:flex;align-items:center;gap:11px;padding:0 20px;border-bottom:1px solid rgb(255 255 255 / 70%)}.wallet-header img{width:37px;filter:brightness(0) invert(1)}.wallet-header div{display:grid}.wallet-header strong{font-size:18px}.wallet-header small{color:var(--muted-white);font-size:14px}.wallet-header>span{margin-left:auto;font-size:13px;font-weight:700}.screen-content{padding:28px 24px 22px}.screen-content.compact{padding-top:18px}.eyebrow{font-size:11px;font-weight:700;text-transform:uppercase}h1{margin:7px 0 9px;font-size:27px;line-height:1.12;letter-spacing:0}.intro{margin:0 0 24px;color:var(--muted-white);line-height:1.5}label{display:block;margin-bottom:8px;font-size:12px;font-weight:700}.input-row{height:49px;display:grid;grid-template-columns:1fr auto;border:1px solid white;background:#fff}.input-row:focus-within,textarea:focus{outline:2px solid rgb(255 255 255 / 28%);outline-offset:2px}.input-row input{min-width:0;border:0;padding:0 13px;color:var(--ink);outline:0}.reveal{border:0;border-left:1px solid #d9e0e5;padding:0 13px;background:#fff;color:var(--blue);font-size:11px;font-weight:700}textarea{width:100%;min-height:82px;margin-bottom:13px;resize:none;border:1px solid white;padding:11px 13px;color:var(--ink);outline:0}.note{display:grid;gap:2px;margin:18px 0 23px;border-left:3px solid var(--accent);padding:13px;background:var(--surface-raised);color:#fff;font-size:12px}.note span{color:var(--dark-muted)}.compact-note{margin:12px 0 14px;padding:10px 13px}.warning{margin:18px 0 25px;border-left:3px solid var(--danger);padding:13px;background:#321c20;color:#ffbbb5;font-size:12px;line-height:1.4}.warning strong{display:block}.primary,.secondary{width:100%;min-height:48px;display:flex;align-items:center;justify-content:center;gap:10px;border:1px solid var(--accent);background:var(--accent);color:#08202b;font-weight:700}.primary span{font-size:18px}.secondary{min-height:42px;margin-top:9px;background:transparent;color:#dcecf3;font-size:12px}.secondary:disabled{border-color:#ffffff59;color:#ffffff7f}.text-button{width:100%;margin-top:8px;border:0;padding:8px;background:transparent;color:var(--muted-white)}.divider{display:flex;align-items:center;gap:10px;margin:17px 0 12px;color:#ffffffad;font-size:12px;text-transform:uppercase}.divider:before,.divider:after{height:1px;flex:1;background:#ffffff4d;content:""}.file-heading{margin-top:20px}.file-picker{min-height:86px;display:flex;align-items:center;gap:13px;margin-bottom:24px;border:1px dashed rgb(255 255 255 / 72%);padding:14px;background:#ffffff1a;cursor:pointer}.file-picker>span:last-child{display:grid;gap:4px}.file-picker small{color:#ffffffad;font-weight:400}.file-icon{width:34px;height:34px;display:grid;flex:0 0 34px;place-items:center;border:1px solid white;font-size:22px;font-weight:400}.visually-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}.loading-screen{position:relative}.loading-brand{position:absolute;top:0;right:0;bottom:0;left:0;display:grid;place-content:center;justify-items:center;gap:34px}.loading-brand img,.large-logo{width:148px;filter:brightness(0) invert(1)}.spinner{width:28px;aspect-ratio:1;border:3px solid rgb(255 255 255 / 28%);border-top-color:#fff;border-radius:50%;animation:spin .85s linear infinite}.loading-screen>p{position:absolute;bottom:35px;width:100%;margin:0;color:#ffffffb8;font-size:12px;text-align:center;text-transform:uppercase}@keyframes spin{to{transform:rotate(360deg)}}.success-mark{width:38px;height:38px;display:grid;place-items:center;border-radius:50%;border:1px solid #55c98a;background:#123727;color:#66dfa0;font-size:22px;font-weight:700}.image-preview{position:relative;height:142px;margin:18px 0;overflow:hidden;border:1px solid var(--dark-line);background:var(--surface)}.image-preview img{width:100%;height:100%;display:block;object-fit:contain}.confirmation{display:grid;grid-template-columns:18px 1fr;gap:9px;align-items:start;margin:14px 0;color:#ffffffd6;font-size:11px;line-height:1.35}.confirmation input{width:16px;height:16px;margin:0}.centered-content{height:100%;display:flex;flex-direction:column;justify-content:center;padding:36px 28px;text-align:center}.centered-content{align-items:stretch}.centered-content .large-logo{align-self:center;width:92px;margin-bottom:25px}.centered-content h1{text-align:center}.centered-content .primary{margin-top:22px}.dashboard-header{height:66px}.account-button{min-width:105px;max-width:132px;height:34px;display:flex;align-items:center;gap:7px;margin-left:auto;overflow:hidden;border:1px solid rgb(255 255 255 / 45%);padding:0 10px;background:transparent;color:#fff;font-size:14px}.account-button>span:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.network-dot{width:7px;height:7px;flex:0 0 7px;border-radius:50%;background:#63d18d}.assets-dashboard{height:calc(100% - 66px);overflow:hidden}.portfolio-balance{padding:22px 22px 19px;border-bottom:1px solid rgb(255 255 255 / 24%);background:var(--blue-deep)}.portfolio-balance>span{color:var(--muted-white);font-size:14px;text-transform:uppercase}.portfolio-balance>strong{display:block;margin-top:4px;font-size:31px;line-height:1.2}.portfolio-balance>strong small{font-size:13px}.portfolio-balance p{max-width:100%;margin:7px 0 0;overflow:hidden;color:#ffffffd1;font-size:13px;text-overflow:ellipsis;white-space:nowrap}.wallet-actions{height:88px;display:grid;grid-template-columns:repeat(4,1fr);border-bottom:1px solid rgb(255 255 255 / 24%)}.wallet-actions button{display:grid;place-items:center;align-content:center;gap:5px;border:0;border-right:1px solid rgb(255 255 255 / 18%);background:transparent;color:#fff;font-size:14px;font-weight:700}.wallet-actions button:last-child{border-right:0}.action-icon{width:29px;height:29px;display:grid;place-items:center;border:1px solid rgb(255 255 255 / 65%);font-size:16px;font-weight:400}.asset-ledger{height:calc(100% - 209px);background:var(--dark);color:#fff}.asset-filter{height:42px;display:grid;grid-template-columns:1fr 1fr;border-bottom:1px solid var(--dark-line);padding:5px 19px;background:#0f1a22}.asset-filter button{border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dark-muted);font-size:14px;font-weight:700}.asset-filter button.active{border-bottom-color:var(--accent);color:#fff}.asset-ledger-heading{height:45px;display:flex;align-items:center;justify-content:space-between;padding:0 19px;border-bottom:1px solid var(--dark-line)}.asset-ledger-heading h1{margin:0;font-size:19px}.asset-ledger-heading button{width:30px;height:30px;border:0;background:transparent;color:var(--accent);font-size:17px}.asset-row{min-height:66px;display:grid;grid-template-columns:38px minmax(0,1fr) auto;gap:11px;align-items:center;padding:10px 19px;border-bottom:1px solid var(--dark-line);background:var(--surface)}.asset-symbol{width:36px;height:36px;display:grid;place-items:center;background:var(--blue);color:#fff;font-size:12px;font-weight:700}.contractless-symbol img{width:25px;filter:brightness(0) invert(1)}.asset-name,.asset-value{min-width:0;display:grid;gap:2px}.asset-name strong,.asset-value strong{overflow:hidden;font-size:16px;text-overflow:ellipsis;white-space:nowrap}.asset-name span,.asset-value span{color:var(--dark-muted);font-size:13px}.asset-value{max-width:125px;text-align:right}.token-list{max-height:calc(100% - 148px);overflow-y:auto}.empty-assets{display:grid;gap:5px;padding:27px 20px;color:var(--dark-muted);text-align:center}.empty-assets strong{color:#dce8ee;font-size:16px}.empty-assets span{font-size:14px}.receive-screen{background:var(--dark)}.receive-screen .wallet-header{background:var(--blue)}.send-screen,.send-review-screen,.send-success-screen{background:var(--dark);color:#fff}.send-screen .wallet-header,.send-review-screen .wallet-header,.send-success-screen .wallet-header{background:var(--blue)}.send-content,.send-review-content,.send-success-content{height:calc(100% - 72px);padding:22px;overflow-y:auto}.send-content{display:grid;align-content:start;gap:17px}.send-content label{color:#fff;font-size:14px}.send-content input,.send-content select{width:100%;min-height:48px;border:1px solid var(--dark-line);padding:0 13px;background:var(--surface);color:#fff;outline:0}.send-content input:focus,.send-content select:focus{border-color:var(--accent)}.send-amount-row{display:grid;grid-template-columns:minmax(0,1fr) auto}.send-amount-row input{border-right:0}.send-amount-row>span{min-width:64px;display:grid;place-items:center;border:1px solid var(--dark-line);background:var(--surface-raised);color:var(--accent);font-weight:700}.field-note{display:block;margin-top:7px;color:var(--dark-muted);font-size:13px}.send-continue{margin-top:5px}.send-review-content{padding:0 22px 24px}.send-review-amount{margin:0 -22px 20px;padding:24px 22px;background:var(--blue-deep)}.send-review-amount>span{color:var(--muted-white);font-size:13px;text-transform:uppercase}.send-review-amount strong{display:block;margin-top:5px;font-size:29px}.send-review-amount small{color:var(--accent);font-size:15px}.send-review-details{margin:0 0 18px}.send-review-details>div{padding:12px 0;border-bottom:1px solid var(--dark-line)}.send-review-details dt{margin-bottom:4px;color:var(--dark-muted);font-size:13px}.send-review-details dd{margin:0;overflow-wrap:anywhere;color:#fff;font-weight:700}.signing-notice{margin:18px 0;padding-left:12px;border-left:3px solid var(--accent);color:var(--dark-muted)}.send-success-content{text-align:center}.send-success-content p{color:var(--dark-muted)}.send-txid{margin:24px 0 14px;padding:14px;border:1px solid var(--dark-line);background:var(--surface);text-align:left}.send-txid span{display:block;margin-bottom:5px;color:var(--dark-muted);font-size:13px}.send-txid strong{overflow-wrap:anywhere}.send-success-content .secondary{margin-bottom:10px}.receive-content{height:calc(100% - 72px);overflow-y:auto;padding:25px 24px 22px;text-align:center}.receive-label{color:var(--accent);font-size:12px;font-weight:700;text-transform:uppercase}.receive-content h1{margin-top:8px}.receive-content>p{margin:0 auto 20px;color:var(--dark-muted);font-size:11px;line-height:1.45}.qr-frame{width:238px;height:238px;display:grid;place-items:center;margin:0 auto 19px;border:1px solid #708693;padding:8px;background:#fff}.qr-frame canvas{width:220px;height:220px;display:block}.receive-address{display:grid;gap:6px;border:1px solid var(--dark-line);padding:13px;background:var(--surface);text-align:left}.receive-address span{color:var(--dark-muted);font-size:11px;font-weight:700;text-transform:uppercase}.receive-address strong{overflow-wrap:anywhere;color:#e5f0f5;font:12px/1.4 Consolas,monospace}.receive-copy{margin-top:13px}.nfts-screen,.nft-detail-screen{background:var(--dark);color:#fff}.nfts-screen .wallet-header,.nft-detail-screen .wallet-header{background:var(--blue)}.header-refresh{width:34px;height:34px;display:grid;place-items:center;margin-left:auto;border:1px solid rgb(255 255 255 / 70%);background:transparent;color:#fff;font-size:18px}.nfts-content,.nft-detail-content{height:calc(100% - 72px);overflow-y:auto}.nfts-summary{min-height:42px;display:flex;align-items:center;justify-content:space-between;padding:0 18px;border-bottom:1px solid var(--dark-line);background:#0f1a22;color:var(--dark-muted);font-size:13px;font-weight:700;text-transform:uppercase}.nfts-summary span:first-child{color:var(--accent)}.nfts-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1px;padding:1px;background:var(--dark-line)}.nft-card{min-width:0;display:grid;align-content:start;border:0;padding:0;background:var(--surface);color:#fff;text-align:left}.nft-card:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.nft-card-media{width:100%;aspect-ratio:1;display:grid;place-items:center;overflow:hidden;background:#17303e;color:var(--accent);font-size:28px;font-weight:700}.nft-card-media img{width:100%;height:100%;display:block;object-fit:cover}.nft-card-identity{min-height:116px;display:grid;align-content:start;gap:3px;padding:11px 12px 13px}.nft-card-identity>span{color:var(--accent);font-size:11px;font-weight:700}.nft-card-identity strong{overflow:hidden;font-size:15px;text-overflow:ellipsis;white-space:nowrap}.nft-card-identity small{overflow:hidden;color:var(--dark-muted);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.nft-card-identity b{margin-top:5px;color:#fff;font-size:12px}.nft-card-identity em{color:#e9c667;font-size:11px;font-style:normal}.nfts-empty{grid-column:1 / -1;min-height:300px;display:grid;place-content:center;gap:6px;padding:30px;background:var(--surface);color:var(--dark-muted);text-align:center}.nfts-empty strong{color:#fff;font-size:17px}.nfts-pagination{min-height:52px;display:grid;grid-template-columns:42px 1fr 42px;align-items:center;gap:10px;padding:7px 14px;border-top:1px solid var(--dark-line);background:#0f1a22;text-align:center}.nfts-pagination[hidden]{display:none}.nfts-pagination button{width:38px;height:38px;border:1px solid var(--dark-line);background:var(--surface);color:var(--accent);font-size:17px}.nfts-pagination button:disabled{color:#61727c}.nfts-pagination span{color:var(--dark-muted);font-size:13px}.nft-detail-media{width:100%;aspect-ratio:16 / 11;display:grid;place-items:center;overflow:hidden;border-bottom:1px solid var(--dark-line);background:#142934}.nft-detail-media img{width:100%;height:100%;display:block;object-fit:contain}.nft-detail-heading{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:15px;align-items:end;padding:18px 20px 14px}.nft-detail-heading>div{min-width:0}.nft-detail-heading span{color:var(--accent);font-size:11px;font-weight:700}.nft-detail-heading h1{overflow-wrap:anywhere;margin:4px 0 0;font-size:23px}.nft-detail-heading>strong{color:#63d18d;font-size:13px;text-align:right}.nft-detail-description{margin:0;padding:0 20px 17px;color:var(--dark-muted);font-size:14px;line-height:1.5}.nft-detail-attributes{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:7px;padding:0 20px 18px}.nft-detail-attributes[hidden]{display:none}.nft-detail-attributes>div{min-width:0;display:grid;gap:2px;border:1px solid var(--dark-line);padding:9px;background:var(--surface-raised)}.nft-detail-attributes span{overflow:hidden;color:var(--dark-muted);font-size:11px;text-overflow:ellipsis;white-space:nowrap}.nft-detail-attributes strong{overflow-wrap:anywhere;font-size:13px}.nft-detail-fields{margin:0;border-top:1px solid var(--dark-line)}.nft-detail-fields>div{display:grid;gap:4px;padding:12px 20px;border-bottom:1px solid var(--dark-line)}.nft-detail-fields dt{color:var(--dark-muted);font-size:12px}.nft-detail-fields dd{margin:0;overflow-wrap:anywhere;color:#fff;font:12px/1.45 Consolas,monospace}.nft-detail-actions{padding:18px 20px 0}.nft-provenance{padding:18px 20px 25px}.nft-provenance h2{margin:0 0 11px;font-size:16px}.nft-provenance p{color:var(--dark-muted)}.nft-history-row{width:100%;display:grid;grid-template-columns:minmax(0,1fr) auto;gap:3px 12px;border:0;padding:10px 0;border-bottom:1px solid var(--dark-line);background:transparent;color:#fff;text-align:left}.nft-history-row:hover,.nft-history-row:focus-visible{background:var(--surface-raised)}.nft-history-row:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.nft-history-row strong{font-size:13px}.nft-history-row span{color:var(--dark-muted);font-size:12px;text-align:right}.nft-history-row small{grid-column:1 / -1;color:var(--accent);font:11px Consolas,monospace}.activity-screen{background:var(--dark);color:#fff}.activity-screen .wallet-header{background:var(--blue)}.activity-content{height:calc(100% - 72px);overflow-y:auto}.activity-summary{min-height:42px;display:flex;align-items:center;justify-content:space-between;padding:0 18px;border-bottom:1px solid var(--dark-line);background:#0f1a22;color:var(--dark-muted);font-size:13px;text-transform:uppercase}.activity-summary strong{color:var(--accent);font-size:13px}.activity-summary>div{display:flex;align-items:center;gap:8px}.activity-summary button{width:30px;height:30px;border:1px solid var(--dark-line);background:transparent;color:var(--accent);font-size:17px}.activity-list{background:var(--surface)}.activity-row{width:100%;min-height:98px;display:grid;grid-template-columns:31px minmax(0,1fr) auto;gap:10px;align-items:center;padding:11px 17px;border-bottom:1px solid var(--dark-line);border-top:0;border-right:0;border-left:0;background:transparent;color:#fff;text-align:left}.activity-row:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.activity-marker{width:29px;height:29px;display:grid;place-items:center;border:1px solid #607987;color:var(--accent);font-size:13px;font-weight:700}.activity-marker.incoming,.activity-status .incoming{color:#63d18d}.activity-marker.outgoing,.activity-status .outgoing{color:#fff}.activity-details,.activity-status{min-width:0;display:grid;gap:2px}.activity-details strong{overflow:hidden;font-size:16px;text-overflow:ellipsis;white-space:nowrap}.activity-details span{color:#c1d0d8;font:13px Consolas,monospace}.activity-details small,.activity-status span{color:var(--dark-muted);font-size:13px}.activity-status{max-width:132px;text-align:right}.activity-status strong{font-size:14px;white-space:nowrap}.activity-status .confirmed{color:#63d18d}.activity-status .pending{color:#e9c667}.activity-empty{display:grid;gap:6px;padding:42px 24px;color:var(--dark-muted);font-size:14px;text-align:center}.activity-empty strong{color:#dce8ee;font-size:16px}.activity-error{color:#ffaaa4}.transaction-screen{background:var(--dark);color:#fff}.transaction-screen .wallet-header{background:var(--blue)}.transaction-confirmed{color:#84e7aa}.transaction-pending{color:#f1d27b}.transaction-content{height:calc(100% - 72px);overflow-y:auto;padding-bottom:24px}.transaction-identity{display:grid;gap:13px;padding:18px;border-bottom:1px solid var(--dark-line);background:var(--surface-raised)}.transaction-identity>div{display:grid;gap:7px}.transaction-identity span,.transaction-field span{color:var(--dark-muted);font-size:12px;font-weight:700;text-transform:uppercase}.transaction-identity strong{overflow-wrap:anywhere;color:#fff;font:13px/1.55 Consolas,monospace}.transaction-identity button{min-height:40px;border:1px solid var(--accent);background:transparent;color:var(--accent);font-size:14px;font-weight:700}.transaction-section{border-top:1px solid var(--dark-line)}.transaction-section h2{margin:0;padding:16px 18px 10px;font-size:16px}.transaction-fields{display:grid}.transaction-field{display:grid;gap:6px;padding:13px 18px;border-bottom:1px solid var(--dark-line);background:var(--surface)}.transaction-field strong{overflow-wrap:anywhere;color:#fff;font-size:15px;font-weight:600;line-height:1.45}.transaction-technical{border-top:1px solid var(--dark-line)}.transaction-technical summary{padding:17px 18px;color:var(--accent);font-size:15px;font-weight:700;cursor:pointer}.technical-field strong{font:12px/1.55 Consolas,monospace;word-break:break-all}.drawer-backdrop{position:absolute;top:0;right:0;bottom:0;left:0;z-index:10;background:#091a278a}.account-drawer{position:absolute;top:0;right:0;bottom:0;z-index:11;width:338px;display:flex;flex-direction:column;border-left:1px solid var(--dark-line);background:var(--dark);color:#fff;transform:translate(100%);transition:transform .18s ease-out}.account-drawer.open{transform:translate(0)}.drawer-header{height:72px;display:flex;align-items:center;justify-content:space-between;padding:0 18px;border-bottom:1px solid var(--dark-line);background:var(--blue);color:#fff}.drawer-header>div{display:grid;gap:2px}.drawer-header strong{font-size:19px}.drawer-header span{color:var(--muted-white);font-size:14px}.drawer-header button{width:34px;height:34px;border:1px solid rgb(255 255 255 / 45%);background:transparent;color:#fff;font-size:23px;line-height:1}.drawer-section{max-height:244px;overflow-y:auto;padding:17px 15px 14px;border-bottom:1px solid var(--dark-line)}.drawer-label{display:block;margin:0 3px 8px;color:var(--dark-muted);font-size:13px;font-weight:700;text-transform:uppercase}.known-address{width:100%;min-height:58px;display:grid;grid-template-columns:minmax(0,1fr) 30px;gap:4px;align-items:center;border:1px solid var(--dark-line);padding:4px;background:var(--surface);color:#fff}.known-address+.known-address{margin-top:7px}.known-address.active-address{border-color:var(--accent);background:var(--surface-active)}.address-select{min-width:0;min-height:48px;display:grid;grid-template-columns:36px minmax(0,1fr) 20px;gap:10px;align-items:center;border:0;padding:5px 6px;background:transparent;color:#fff;text-align:left}.rename-address{width:28px;height:34px;border:0;background:transparent;color:var(--accent);font-size:16px}.address-avatar{width:34px;height:34px;display:grid;place-items:center;background:#204f70}.address-avatar img{width:24px;filter:brightness(0) invert(1)}.address-details{min-width:0;display:grid;gap:2px}.address-details strong{font-size:15px}.address-details small{overflow:hidden;color:var(--dark-muted);font-size:13px;text-overflow:ellipsis;white-space:nowrap}.selected-mark{color:var(--success);font-size:14px;font-weight:700}.drawer-navigation{display:grid;padding:8px 0}.drawer-navigation button{min-height:72px;display:grid;grid-template-columns:34px minmax(0,1fr) 16px;gap:10px;align-items:center;border:0;border-bottom:1px solid var(--dark-line);padding:9px 18px;background:transparent;color:#fff;text-align:left}.drawer-navigation button>span:nth-child(2){display:grid;gap:2px}.drawer-navigation strong{font-size:16px}.drawer-navigation small{color:var(--dark-muted);font-size:13px}.menu-icon{width:32px;height:32px;display:grid;place-items:center;border:1px solid #607987;color:var(--accent);font-size:15px;font-weight:700}.menu-arrow{color:var(--dark-muted);font-size:20px;text-align:right}.drawer-lock{min-height:46px;display:flex;align-items:center;justify-content:center;gap:8px;margin:auto 15px 15px;border:1px solid var(--dark-line);background:var(--surface-raised);color:#dce8ee;font-size:14px;font-weight:700}.header-back{width:34px;height:34px;border:1px solid rgb(255 255 255 / 45%);background:transparent;color:#fff;font-size:18px}.settings-screen{background:var(--dark);color:#fff}.settings-screen .wallet-header{background:var(--blue);color:#fff}.settings-content{height:calc(100% - 72px);overflow-y:auto;padding-bottom:20px}.settings-group{padding:18px 20px;border-bottom:1px solid var(--dark-line);background:var(--surface)}.settings-heading{display:grid;gap:3px;margin-bottom:15px}.settings-heading strong{font-size:13px}.settings-heading span{color:var(--dark-muted);font-size:12px;line-height:1.4}.settings-group label{color:#b7c6ce;font-size:12px;text-transform:uppercase}.settings-group input,.settings-group select{width:100%;height:44px;border:1px solid #8699a5;padding:0 11px;background:#fff;color:var(--ink);outline:0}.settings-group input:focus,.settings-group select:focus{border-color:var(--blue);outline:2px solid rgb(33 103 165 / 14%)}.settings-save{width:calc(100% - 40px);margin:16px 20px;border-color:var(--accent);background:var(--accent);color:#08202b}.backup-settings{padding-right:0;padding-left:0}.backup-settings .settings-heading{padding:0 20px}.settings-action{width:100%;min-height:61px;display:grid;grid-template-columns:34px minmax(0,1fr) 16px;gap:10px;align-items:center;border:0;border-top:1px solid var(--dark-line);padding:9px 20px;background:transparent;color:#fff;text-align:left}.settings-action:last-child{border-bottom:1px solid var(--dark-line)}.settings-action>span:nth-child(2){display:grid;gap:2px}.settings-action strong{font-size:14px}.settings-action small{color:var(--dark-muted);font-size:11px}.settings-action>span:last-child{color:var(--dark-muted);font-size:20px}.settings-action-icon{width:32px;height:32px;display:grid;place-items:center;border:1px solid #607987;color:var(--accent);font-size:15px;font-weight:700}.private-key-result{margin:16px 20px 0;border:1px solid var(--dark-line);padding:13px;background:var(--surface-raised)}.private-key-result>div{display:flex;align-items:center;justify-content:space-between;margin-bottom:9px}.private-key-result>div>strong{font-size:11px;text-transform:uppercase}.private-key-result>div>button{width:28px;height:28px;border:0;background:transparent;color:var(--dark-muted);font-size:19px}.private-key-result textarea{height:95px;min-height:95px;margin:0 0 10px;border:1px solid #8699a5;padding:9px;background:#fff;color:var(--ink);font-size:11px}.private-key-result .secondary{border-color:var(--accent);color:var(--accent)}.modal-backdrop{position:absolute;top:0;right:0;bottom:0;left:0;z-index:30;background:#091a27ad}.backup-key-modal{position:absolute;top:50%;right:20px;left:20px;z-index:31;border:1px solid white;background:var(--blue);color:#fff;transform:translateY(-50%)}.backup-key-modal>header{min-height:65px;display:flex;align-items:center;justify-content:space-between;padding:12px 15px;border-bottom:1px solid rgb(255 255 255 / 40%)}.backup-key-modal>header>div{display:grid;gap:2px}.backup-key-modal>header strong{font-size:13px}.backup-key-modal>header span{color:var(--muted-white);font-size:11px}.backup-key-modal>header button{width:30px;height:30px;border:1px solid rgb(255 255 255 / 45%);background:transparent;color:#fff;font-size:20px}.backup-key-modal>div{padding:17px 15px}.backup-key-modal .primary{margin-top:16px}#notice{position:absolute;right:18px;bottom:14px;left:18px;z-index:40;margin:0;padding:10px 12px;border:1px solid #8d4448;border-left:3px solid #ff7168;background:#321c20;color:#ffc0bb;font-size:11px}#notice:empty{display:none}.provider-approval-screen{display:flex;flex-direction:column}.provider-approval-screen .screen-content{min-height:0;flex:1;overflow-y:auto;padding-bottom:18px}.approval-context{display:flex;align-items:center;justify-content:space-between;gap:12px}.approval-context .eyebrow{min-width:0;overflow-wrap:anywhere}.risk-label{flex:0 0 auto;padding:5px 8px;border:1px solid currentColor;font-size:11px;font-weight:700;text-transform:uppercase}.risk-safe{background:#123b2d;color:#63e5a9}.risk-low{background:#403612;color:#ffe16c}.risk-high{background:#481f24;color:#ff8b8b}.approval-details{display:grid;grid-template-columns:minmax(100px,.8fr) minmax(0,1.4fr);margin:20px 0;border:1px solid #315466;background:#091923}.approval-details dt,.approval-details dd{min-width:0;margin:0;padding:11px 12px;border-bottom:1px solid #203d4c;overflow-wrap:anywhere}.approval-details dt{color:#85dce8;font-size:12px;font-weight:700;text-transform:capitalize}.approval-details dd{color:#f5f9fb;font:13px/1.45 Arial,Helvetica,sans-serif;white-space:pre-wrap}.approval-details dt:last-of-type,.approval-details dd:last-of-type{border-bottom:0}.approval-actions{display:grid;flex:0 0 auto;grid-template-columns:1fr 1fr;gap:10px;padding:14px 24px 18px;border-top:1px solid rgb(255 255 255 / 35%);background:var(--blue-deep)}.approval-actions button{min-height:48px;margin:0}.approval-actions button.is-processing:before{width:15px;height:15px;content:"";border:2px solid currentcolor;border-right-color:transparent;border-radius:50%;animation:approval-spin .7s linear infinite}.approval-actions button:disabled{opacity:.72}@keyframes approval-spin{to{transform:rotate(360deg)}} diff --git a/extension/dist/assets/print-DTb91-bp.css b/extension/dist/assets/print-DTb91-bp.css deleted file mode 100644 index b6c42aa..0000000 --- a/extension/dist/assets/print-DTb91-bp.css +++ /dev/null @@ -1 +0,0 @@ -*{box-sizing:border-box}body{max-width:760px;margin:0 auto;padding:34px;color:#111820;font:14px/1.45 Arial,Helvetica,sans-serif}header{display:flex;align-items:center;gap:15px;padding-bottom:18px;border-bottom:3px solid #2167a5}header img{width:58px}h1{margin:0;font-size:24px}header p{margin:2px 0 0;color:#5c6972}.warning{margin:22px 0;border:2px solid #9b1c1c;padding:12px;color:#7a1111;font-weight:700}section{margin-top:18px}h2{margin:0 0 7px;color:#42515b;font-size:12px;text-transform:uppercase}pre{margin:0;overflow-wrap:anywhere;white-space:pre-wrap;border:1px solid #aebac2;padding:11px;font:10px/1.35 Consolas,monospace}.print-error{color:#9b1c1c;font-weight:700}@media print{body{max-width:none;padding:0}} diff --git a/extension/dist/background.js b/extension/dist/background.js deleted file mode 100644 index d670490..0000000 --- a/extension/dist/background.js +++ /dev/null @@ -1,3 +0,0 @@ -import{c as yt}from"./chunks/core-CvwXoH-U.js";const F="contractlessWallet",M="contractlessWallets",V="contractlessSettings",L="contractlessAutoLock",K="contractlessUnlockedWallet",j="contractlessApplicationSessions",ct=12e4,vt=10,bt={apiUrl:"https://api.contractless.dev",autoLockMinutes:60};let s;const J="pending-provider-approvals";async function k(){const e=await chrome.storage.local.get(V);return{...bt,...e[V]??{}}}function lt(e){const t=JSON.parse(e);if(typeof t.short_address!="string"||typeof t.public_key!="string")throw new Error("The encrypted wallet metadata is invalid.");return{address:t.short_address,publicKey:t.public_key}}async function $(){const e=await chrome.storage.local.get([M,F]),t=e[M];if((t==null?void 0:t.version)===1&&Array.isArray(t.wallets))return t;const a=e[F];if(typeof a!="string")return{version:1,wallets:[]};const i=lt(a),d={id:crypto.randomUUID(),label:"Contractless Account 1",address:i.address,publicKey:i.publicKey,walletJson:a},l={version:1,activeWalletId:d.id,wallets:[d]};return await chrome.storage.local.set({[M]:l}),await chrome.storage.local.remove(F),l}async function H(e){await chrome.storage.local.set({[M]:e})}function P(e){return e.wallets.find(t=>t.id===e.activeWalletId)??e.wallets[0]}async function X(e){const t=await $(),a=lt(e),i=t.wallets.find(l=>l.address===a.address);if(i)return i.walletJson=e,i.publicKey=a.publicKey,t.activeWalletId=i.id,await H(t),i;const d={id:crypto.randomUUID(),label:`Contractless Account ${t.wallets.length+1}`,address:a.address,publicKey:a.publicKey,walletJson:e};return t.wallets.push(d),t.activeWalletId=d.id,await H(t),d}async function E(){await dt();const e=await $(),t=P(e),a=await k();return{exists:e.wallets.length>0,unlocked:!!(s&&s.walletId===(t==null?void 0:t.id)),activeWalletId:t==null?void 0:t.id,activeWalletLabel:t==null?void 0:t.label,address:s==null?void 0:s.short_address,publicKey:s==null?void 0:s.public_key,wallets:e.wallets.map(i=>({id:i.id,label:i.label,address:i.address,publicKey:i.publicKey,active:i.id===(t==null?void 0:t.id)})),apiUrl:a.apiUrl,autoLockMinutes:a.autoLockMinutes}}async function b(){if(!s)return;const e=await k();s.expiresAt=Date.now()+e.autoLockMinutes*6e4,await chrome.storage.session.set({[K]:s}),await chrome.alarms.clear(L),await chrome.alarms.create(L,{when:s.expiresAt})}function kt(e,t){const a=new Uint8Array(e);let i="";const d=32768;for(let l=0;l{});if(!l.ok||(f==null?void 0:f.success)!==!0)throw new Error((f==null?void 0:f.error)??`Wallet registration failed with HTTP ${l.status}.`);return f.data}async function St(e,t){var f;const a=await k(),i=e.create_handshake_proof(t.public_key,t.private_key),d=await fetch(`${a.apiUrl}/api/v1/addresses/registration?address=${encodeURIComponent(t.short_address)}`,{headers:{"X-Contractless-Address":t.short_address,"X-Contractless-Public-Key":t.public_key,"X-Contractless-Signature":i}}),l=await d.json().catch(()=>{});if(!d.ok||(l==null?void 0:l.success)!==!0)throw new Error((l==null?void 0:l.error)??`Wallet registration lookup failed with HTTP ${d.status}.`);((f=l.data)==null?void 0:f.registered)!==!0&&await Y(e,t)}async function dt(){if(s){if(s.expiresAt>Date.now())return;await R();return}const t=(await chrome.storage.session.get(K))[K];if(!t||t.expiresAt<=Date.now()){await chrome.storage.session.remove(K);return}t.sessionId||(t.sessionId=crypto.randomUUID(),await wt(),await chrome.storage.session.set({[K]:t})),s=t}async function R(){s&&(s.private_key="",s=void 0),await chrome.storage.session.remove([K,j]),await chrome.alarms.clear(L)}async function Q(){const t=(await chrome.storage.session.get(j))[j];return Array.isArray(t)?t:[]}async function pt(e){await chrome.storage.session.set({[j]:e})}async function wt(){await chrome.storage.session.remove(j)}function Tt(e){const t=crypto.getRandomValues(new Uint8Array(e));return Array.from(t,a=>a.toString(16).padStart(2,"0")).join("")}async function Et(e){const t=await crypto.subtle.digest("SHA-256",new TextEncoder().encode(e));return Array.from(new Uint8Array(t),a=>a.toString(16).padStart(2,"0")).join("")}function O(e){return!e.params||typeof e.params!="object"?{}:e.params}function C(e){const t=String(e??"").trim();if(!/^[A-Za-z0-9_-]{5,32}$/.test(t))throw new Error("The application ID must contain 5 to 32 URL-safe characters.");return t}function Z(e,t){if(String(e.origin??"")!==t)throw new Error("The application origin does not match the requesting website.")}function ut(e){const t=Number(e),a=Math.floor(Date.now()/1e3);if(!Number.isInteger(t)||Math.abs(a-t)>300)throw new Error("The application connection timestamp must be within five minutes.");return t}function ht(e){const t=String(e??"").trim().toLowerCase();if(!/^[0-9a-f]{32,128}$/.test(t)||t.length%2!==0)throw new Error("The application nonce must contain 16 to 64 random hexadecimal bytes.");return t}function gt(e){const t=String(e??"").trim();if(!t||new TextEncoder().encode(t).length>75)throw new Error("The application connection message must contain 1 to 75 bytes.");return t}function ft(e){const t=String(e??"").trim();if(!t||new TextEncoder().encode(t).length>75)throw new Error("A signed website message must contain 1 to 75 bytes.");return t}function st(e,t){if(e==="contractless_connect"||e==="contractless_signMessage")return"safe";const a=t.transaction;if(!a||typeof a!="object")return"high";const i=Number(a.txtype);return Number.isInteger(i)&&i>=100&&i<=113?"low":"high"}function _t(e){if(!e||typeof e!="object")throw new Error("A complete transaction object is required.");const t=e,a=Number(t.txtype);if(!Number.isInteger(a))throw new Error("The transaction type is invalid.");if(a===6||a===7)throw new Error("Swaps and loan creation require a staged signing workflow.");return t}function z(e){if(!e||typeof e!="object")throw new Error("A complete or partially signed transaction object is required.");const t=e,a=t.unsigned_swap??t.unsigned_loan_contract??t;if(!a||typeof a!="object")throw new Error("The unsigned transaction fields are missing.");const i=Number(a.txtype);if(i!==6&&i!==7)throw new Error("Staged signing is only available for swaps and loan creation.");return t}async function rt(e,t){var S;if(!s)throw new Error("Wallet is locked.");const a=t.unsigned_swap??t.unsigned_loan_contract??t;if(!a||typeof a!="object")return;const i=a,d=Number(i.txtype),l=d===2?[["Receiving",String(i.receiver??"")]]:d===6?[["First swap participant",String(i.sender1??"")],["Second swap participant",String(i.sender2??"")]]:d===7?[["Lender",String(i.lender??"")],["Borrower",String(i.borrower??"")]]:[];if(l.length===0)return;e.inspect_transaction_request(JSON.stringify(t));const f=await k(),v=e.create_handshake_proof(s.public_key,s.private_key),y={"X-Contractless-Address":s.short_address,"X-Contractless-Public-Key":s.public_key,"X-Contractless-Signature":v},T=new Map;for(const[x,U]of l){const A=U.trim().toLowerCase();let I=T.get(A);if(I===void 0){const r=await fetch(`${f.apiUrl}/api/v1/addresses/registration?address=${encodeURIComponent(A)}`,{headers:y}),o=await r.json().catch(()=>{});if(!r.ok||(o==null?void 0:o.success)!==!0)throw new Error((o==null?void 0:o.error)??`Address registration lookup failed with HTTP ${r.status}.`);I=((S=o.data)==null?void 0:S.registered)===!0,T.set(A,I)}if(!I)throw new Error(`${x} wallet is not registered.`)}}async function mt(e,t){if(t.complete!==!0||typeof t.bytes_hex!="string"||typeof t.hash!="string")throw new Error("The transaction could not be completed.");if(!s)throw new Error("Wallet is locked.");const a=await k(),i=e.create_handshake_proof(s.public_key,s.private_key),d=await fetch(`${a.apiUrl}/api/v1/transactions/broadcast`,{method:"POST",headers:{"Content-Type":"application/json","X-Contractless-Address":s.short_address,"X-Contractless-Public-Key":s.public_key,"X-Contractless-Signature":i},body:JSON.stringify({transaction_hex:t.bytes_hex})}),l=await d.json().catch(()=>{});if(!d.ok||(l==null?void 0:l.success)!==!0)throw new Error((l==null?void 0:l.error)??`Transaction broadcast failed with HTTP ${d.status}.`);return await b(),{txid:t.hash,bytes:t.bytes_hex,broadcast:l.data}}async function N(e,t){if(!s)throw new Error("Wallet is locked.");Z(e,t);const a=C(e.appId),i=String(e.accessKey??""),d=(await Q()).find(l=>l.origin===t&&l.appId===a&&l.accessKey===i&&l.walletId===(s==null?void 0:s.walletId)&&l.unlockSessionId===(s==null?void 0:s.sessionId));if(!d)throw new Error("The application session is invalid or has expired. Reconnect the wallet.");return d}async function B(){const t=(await chrome.storage.session.get(J))[J],a=Array.isArray(t)?t.filter(y=>typeof y=="string"&&y.length>0):typeof t=="string"&&t.length>0?[t]:[];if(a.length===0)return[];const i=a.map(y=>`approval:${y}`),d=await chrome.storage.session.get(i),l=Date.now(),f=[],v=[];for(const y of a){const T=`approval:${y}`,S=d[T];!S||l-S.createdAt>=ct?v.push(T):f.push(y)}return(v.length>0||f.length!==a.length)&&(await chrome.storage.session.set({[J]:f}),v.length>0&&await chrome.storage.session.remove(v)),f}async function G(e){const t=(await B()).filter(a=>a!==e);return await chrome.storage.session.set({[J]:t}),t}async function ot(e){const t=await B(),a=await chrome.storage.session.get(t.map(d=>`approval:${d}`));if(e.method==="contractless_connect"&&t.some(d=>{const l=a[`approval:${d}`];if(!l||l.method!=="contractless_connect")return!1;const f=O(l),v=O(e);return l.origin===e.origin&&f.appId===v.appId}))throw new Error("This application already has a wallet connection request pending.");if(t.length>=vt)throw new Error("The wallet approval queue is full. Resolve a pending request first.");await chrome.storage.session.set({[J]:[...t,e.id],[`approval:${e.id}`]:e});try{await chrome.action.openPopup()}catch{}}async function nt(e){const t=`approval-result:${e}`,a=Date.now()+ct;for(;Date.now()setTimeout(d,150))}throw await chrome.storage.session.remove([`approval:${e}`,t]),await G(e),new Error("Wallet approval request expired.")}function At(e){const t=e.url??e.origin;if(!t)throw new Error("The requesting website origin is unavailable.");const a=new URL(t).origin;if(a==="null")throw new Error("Requests from opaque origins are not supported.");return a}async function it(e,t){if(!s)throw new Error("Wallet is locked.");switch(await b(),t.method){case"contractless_connect":{const a=O(t);Z(a,t.origin);const i=String(a.walletSessionId??"");if(i&&i!==s.sessionId)throw new Error("The active wallet changed while the connection was being approved.");const d=C(a.appId),l=ut(a.timestamp),f=ht(a.nonce),v=gt(a.message),y=Tt(32),T=await Et(y),S=Math.floor(Date.now()/1e3),x=Math.min(S+900,Math.floor(s.expiresAt/1e3)),U=["Contractless application connection",`Application ID: ${d}`,`Origin: ${t.origin}`,`Requested timestamp: ${l}`,`Message: ${v}`,`Session key hash: ${T}`].join(` -`),A=JSON.parse(e.sign_message_request(JSON.stringify({origin:t.origin,message:U,nonce:f,issued_at:S,expires_at:x}),s.private_key,s.public_key)),I={origin:t.origin,appId:d,accessKey:y,walletId:s.walletId,unlockSessionId:s.sessionId,createdAt:Date.now()},r=await Q();return r.push(I),await pt(r),{address:s.short_address,publicKey:s.public_key,signature:A.signature,proof:A,accessKey:y,appId:d,origin:t.origin,sessionExpiresAt:s.expiresAt}}case"contractless_signMessage":{const a=O(t);await N(a,t.origin);const i=Math.floor(Date.now()/1e3),d=Number(a.expires_at??i+300),l=C(a.appId),f={origin:t.origin,message:["Contractless application message",`Application ID: ${l}`,`Message: ${ft(a.message)}`].join(` -`),nonce:String(a.nonce??""),issued_at:i,expires_at:d};return JSON.parse(e.sign_message_request(JSON.stringify(f),s.private_key,s.public_key))}case"contractless_sendTransaction":{const a=O(t);await N(a,t.origin);const i=_t(a.transaction),d=JSON.parse(e.sign_transaction_request(JSON.stringify(i),s.private_key,s.public_key,1));return mt(e,d)}case"contractless_signDualTransaction":{const a=O(t);await N(a,t.origin);const i=z(a.transaction),d=Number(a.signerSlot);if(d!==1&&d!==2)throw new Error("The signer slot must be 1 or 2.");const l=JSON.parse(e.sign_transaction_request(JSON.stringify(i),s.private_key,s.public_key,d));return{complete:!1,txid:l.hash,unsignedBytes:l.unsigned_bytes_hex,canonicalUnsignedJson:JSON.parse(e.inspect_transaction_request(JSON.stringify(i))).canonical_unsigned_json,signedTransaction:l.signed_transaction,signature:d===1?l.signature1:l.signature2,signature1:l.signature1,signature2:l.signature2,signerSlot:d,signerPublicKey:s.public_key}}default:throw new Error("The website requested an unsupported wallet method.")}}async function It(e,t){var i,d,l,f,v,y,T,S,x,U,A,I;const a=await yt();switch(await dt(),e.type){case"status":return E();case"create-wallet":{const r=String(e.password),o=a.generate_browser_wallet(r),n=JSON.parse(a.unlock_browser_wallet(o,r));await Y(a,n);const u=await X(o);return await W({walletId:u.id,...n}),E()}case"import-wallet":{const r=a.import_legacy_wallet(String(e.walletJson),String(e.legacyPassword),String(e.password)),o=await X(r),n=JSON.parse(a.unlock_browser_wallet(r,String(e.password)));return await W({walletId:o.id,...n}),E()}case"import-wallet-image":{const r=String(e.password),o=a.import_private_key_image(String(e.imageBase64),String(e.imagePassword),r),n=await X(o),u=JSON.parse(a.unlock_browser_wallet(o,r));return await W({walletId:n.id,...u}),E()}case"import-private-key":{const r=String(e.password),o=a.import_private_key(String(e.privateKey),r),n=await X(o),u=JSON.parse(a.unlock_browser_wallet(o,r));return await W({walletId:n.id,...u}),E()}case"unlock":{const r=await $(),o=P(r);if(!o)throw new Error("No wallet exists.");const n=JSON.parse(a.unlock_browser_wallet(o.walletJson,String(e.password)));await W({walletId:o.id,...n});try{await St(a,n)}catch(u){console.warn("Automatic wallet registration failed during unlock.",u)}return E()}case"switch-wallet":{const r=await $(),o=String(e.walletId);if(!r.wallets.some(n=>n.id===o))throw new Error("The selected wallet does not exist.");return await R(),r.activeWalletId=o,await H(r),E()}case"rename-wallet":{const r=await $(),o=r.wallets.find(u=>u.id===String(e.walletId));if(!o)throw new Error("The selected wallet does not exist.");const n=String(e.label).trim();if(n.length<1||n.length>40)throw new Error("Wallet labels must contain between 1 and 40 characters.");return o.label=n,await H(r),E()}case"lock":return await R(),E();case"save-settings":{const r={apiUrl:String(e.apiUrl).replace(/\/+$/,""),autoLockMinutes:Math.max(1,Number(e.autoLockMinutes))};return await chrome.storage.local.set({[V]:r}),await b(),E()}case"register-wallet":{if(!s)throw new Error("Wallet is locked.");const r=await Y(a,s);return await b(),r}case"wallet-balances":{if(!s)throw new Error("Wallet is locked.");const r=await k(),o=a.create_handshake_proof(s.public_key,s.private_key),n={"X-Contractless-Address":s.short_address,"X-Contractless-Public-Key":s.public_key,"X-Contractless-Signature":o},u=encodeURIComponent(s.short_address),[c,h,w]=await Promise.all([fetch(`${r.apiUrl}/api/v1/balances?address=${u}`,{headers:n}),fetch(`${r.apiUrl}/api/v1/tokens`,{headers:n}),fetch(`${r.apiUrl}/api/v1/nfts`,{headers:n})]),[p,_,g]=await Promise.all([c.json().catch(()=>{}),h.json().catch(()=>{}),w.json().catch(()=>{})]);if(!c.ok||(p==null?void 0:p.success)!==!0)throw new Error((p==null?void 0:p.error)??`Balance lookup failed with HTTP ${c.status}.`);return await b(),{address:s.short_address,balances:((i=p.data)==null?void 0:i.balances)??[],tokens:h.ok&&(_==null?void 0:_.success)===!0?((d=_.data)==null?void 0:d.tokens)??[]:[],nfts:w.ok&&(g==null?void 0:g.success)===!0?((l=g.data)==null?void 0:l.nfts)??[]:[],tokenCatalogError:h.ok&&(_==null?void 0:_.success)===!0?void 0:(_==null?void 0:_.error)??`Token lookup failed with HTTP ${h.status}.`,nftCatalogError:w.ok&&(g==null?void 0:g.success)===!0?void 0:(g==null?void 0:g.error)??`NFT lookup failed with HTTP ${w.status}.`}}case"wallet-nft-details":{if(!s)throw new Error("Wallet is locked.");const r=String(e.name??"").trim(),o=Number(e.series??0);if(!r||r.length>15||!Number.isInteger(o)||o<0||o>4294967295)throw new Error("A valid NFT or RWA identifier is required.");const n=await k(),u=a.create_handshake_proof(s.public_key,s.private_key),c={"X-Contractless-Address":s.short_address,"X-Contractless-Public-Key":s.public_key,"X-Contractless-Signature":u},h=`name=${encodeURIComponent(r)}&series=${o}`,[w,p]=await Promise.all([fetch(`${n.apiUrl}/api/v1/nfts/details?${h}`,{headers:c}),fetch(`${n.apiUrl}/api/v1/nfts/media?${h}`,{headers:c})]),[_,g]=await Promise.all([w.json().catch(()=>{}),p.json().catch(()=>{})]);if(!w.ok||(_==null?void 0:_.success)!==!0)throw new Error((_==null?void 0:_.error)??`NFT details lookup failed with HTTP ${w.status}.`);let m="",tt=!1,et={},D;if(p.ok&&(g==null?void 0:g.success)===!0){et=(f=g.data)!=null&&f.metadata&&typeof g.data.metadata=="object"?g.data.metadata:{},tt=((v=g.data)==null?void 0:v.image_available)===!0;const at=String(((y=g.data)==null?void 0:y.image_url)??"");if(at)try{const q=await fetch(new URL(at,`${n.apiUrl}/`).toString(),{headers:c});q.ok?m=kt(await q.arrayBuffer(),q.headers.get("Content-Type")??"image/png"):D=`NFT image returned HTTP ${q.status}.`}catch{D="NFT image could not be retrieved."}}else D=(g==null?void 0:g.error)??`NFT media lookup failed with HTTP ${p.status}.`;return await b(),{..._.data,metadata:et,image_data_url:m,image_available:tt,media_error:D}}case"wallet-receive-address":{if(!s)throw new Error("Wallet is locked.");const r=await k(),o=a.create_handshake_proof(s.public_key,s.private_key),n=encodeURIComponent(s.short_address),u=await fetch(`${r.apiUrl}/api/v1/addresses/vanity?address=${n}`,{headers:{"X-Contractless-Address":s.short_address,"X-Contractless-Public-Key":s.public_key,"X-Contractless-Signature":o}}),c=await u.json().catch(()=>{});if(!u.ok||(c==null?void 0:c.success)!==!0)throw new Error((c==null?void 0:c.error)??`Vanity address lookup failed with HTTP ${u.status}.`);await b();const h=typeof((T=c.data)==null?void 0:T.vanity_address)=="string"&&c.data.vanity_address.trim()!==""?c.data.vanity_address:void 0;return{shortAddress:s.short_address,receiveAddress:h??s.short_address,vanity:!!h}}case"wallet-prepare-transfer":{if(!s)throw new Error("Wallet is locked.");const r=await k(),o=a.create_handshake_proof(s.public_key,s.private_key),n={"X-Contractless-Address":s.short_address,"X-Contractless-Public-Key":s.public_key,"X-Contractless-Signature":o},u=String(e.receiver??"").trim().toLowerCase(),c=s.short_address.endsWith(".cltc")?"cltc":"clc";let h=u;if(new RegExp(`^[0-9a-f]{40}\\.${c}$`).test(u)){const g=await fetch(`${r.apiUrl}/api/v1/addresses/registration?address=${encodeURIComponent(h)}`,{headers:n}),m=await g.json().catch(()=>{});if(!g.ok||(m==null?void 0:m.success)!==!0)throw new Error((m==null?void 0:m.error)??`Address lookup failed with HTTP ${g.status}.`);if(((x=m.data)==null?void 0:x.registered)!==!0)throw new Error("The receiving wallet is not registered.")}else{if(!new RegExp(`^[a-z]{1,20}\\.${c}$`).test(u))throw new Error(`Enter a valid Contractless ${c.toUpperCase()} address.`);const g=await fetch(`${r.apiUrl}/api/v1/addresses/vanity/resolve?address=${encodeURIComponent(u)}`,{headers:n}),m=await g.json().catch(()=>{});if(!g.ok||(m==null?void 0:m.success)!==!0)throw new Error((m==null?void 0:m.error)??`Vanity address lookup failed with HTTP ${g.status}.`);if(h=String(((S=m.data)==null?void 0:S.owner_address)??""),!h)throw new Error("That vanity address is not registered.")}const w=Number(e.nftSeries??0);if(!Number.isInteger(w)||w<0||w>4294967295)throw new Error("The NFT/RWA series number is invalid.");const p={txtype:2,time:Math.floor(Date.now()/1e3),value:String(e.valueAtomic??""),coin:String(e.asset??"").trim().padEnd(15," "),nft_series:w,sender:s.short_address,receiver:h,txfee:String(e.feeAtomic??"")},_=JSON.parse(a.inspect_transaction_request(JSON.stringify(p)));return await b(),{transaction:p,review:_.review,hash:_.hash,receiverInput:u}}case"wallet-broadcast-transfer":{if(!s)throw new Error("Wallet is locked.");const r=e.transaction;if(!r||typeof r!="object")throw new Error("The reviewed transfer is unavailable.");const o=JSON.parse(a.sign_transaction_request(JSON.stringify(r),s.private_key,s.public_key,1));return mt(a,o)}case"wallet-activity":{if(!s)throw new Error("Wallet is locked.");const r=await k(),o=a.create_handshake_proof(s.public_key,s.private_key),n=encodeURIComponent(s.short_address),u={"X-Contractless-Address":s.short_address,"X-Contractless-Public-Key":s.public_key,"X-Contractless-Signature":o},[c,h]=await Promise.all([fetch(`${r.apiUrl}/api/v1/addresses/latest?address=${n}&limit=25`,{headers:u}),fetch(`${r.apiUrl}/api/v1/height`,{headers:u})]),[w,p]=await Promise.all([c.json().catch(()=>{}),h.json().catch(()=>{})]);if(!c.ok||(w==null?void 0:w.success)!==!0)throw new Error((w==null?void 0:w.error)??`Activity lookup failed with HTTP ${c.status}.`);if(!h.ok||(p==null?void 0:p.success)!==!0)throw new Error((p==null?void 0:p.error)??`Block height lookup failed with HTTP ${h.status}.`);return await b(),{address:s.short_address,current_height:Number(((U=p.data)==null?void 0:U.height)??0),transactions:Array.isArray((A=w.data)==null?void 0:A.transactions)?w.data.transactions:[]}}case"wallet-transaction":{if(!s)throw new Error("Wallet is locked.");const r=String(e.txid);if(!/^[0-9a-f]{64}$/i.test(r))throw new Error("A valid transaction ID is required.");const o=await k(),n=a.create_handshake_proof(s.public_key,s.private_key),u={"X-Contractless-Address":s.short_address,"X-Contractless-Public-Key":s.public_key,"X-Contractless-Signature":n},[c,h]=await Promise.all([fetch(`${o.apiUrl}/api/v1/transactions/lookup?txid=${encodeURIComponent(r)}`,{headers:u}),fetch(`${o.apiUrl}/api/v1/height`,{headers:u})]),[w,p]=await Promise.all([c.json().catch(()=>{}),h.json().catch(()=>{})]);if(!c.ok||(w==null?void 0:w.success)!==!0)throw new Error((w==null?void 0:w.error)??`Transaction lookup failed with HTTP ${c.status}.`);if(!h.ok||(p==null?void 0:p.success)!==!0)throw new Error((p==null?void 0:p.error)??`Block height lookup failed with HTTP ${h.status}.`);return await b(),{...w.data,current_height:Number(((I=p.data)==null?void 0:I.height)??0)}}case"export-wallet":{const r=P(await $());if(!r)throw new Error("No wallet exists.");return r.walletJson}case"export-legacy-wallet":{const r=P(await $());if(!r)throw new Error("No wallet exists.");return a.export_legacy_wallet(r.walletJson,String(e.password),String(e.legacyPassword))}case"export-private-key-image":{const r=P(await $());if(!r)throw new Error("No wallet exists.");const o=JSON.parse(a.export_legacy_wallet(r.walletJson,String(e.password),String(e.imagePassword)));if(typeof o.private_key!="string")throw new Error("The wallet image could not be created.");return o.private_key}case"reveal-private-key":{const r=P(await $());if(!r)throw new Error("No wallet exists.");const o=JSON.parse(a.unlock_browser_wallet(r.walletJson,String(e.password)));if(typeof o.private_key!="string")throw new Error("The private key could not be decrypted.");return await b(),{label:r.label,address:r.address,privateKey:o.private_key}}case"provider-request":{const r=At(t),o=String(e.method),n=e.params&&typeof e.params=="object"?e.params:{};if(o==="contractless_detect")return{installed:!0,providerVersion:"1.0.0"};if(o==="contractless_connect"){Z(n,r);const c=C(n.appId),h=ut(n.timestamp);ht(n.nonce);const w=gt(n.message),p={id:crypto.randomUUID(),method:o,params:{...n,walletSessionId:s==null?void 0:s.sessionId},origin:r,createdAt:Date.now(),risk:st(o,n),display:{request:"Connect application",application_id:c,website:r,wallet_address:(s==null?void 0:s.short_address)??"Unlock wallet to continue",message:w,requested_timestamp:h,access:"Address access and future wallet requests until this wallet locks"}};if(await ot(p),!await nt(p.id))throw new Error("The wallet connection request was rejected.");return it(a,p)}if(o==="contractless_accounts")try{return await N(n,r),s?[s.short_address]:[]}catch{return[]}if(o==="contractless_balances"){if(await N(n,r),!s)throw new Error("Wallet is locked.");const c=await k(),h=a.create_handshake_proof(s.public_key,s.private_key),w=await fetch(`${c.apiUrl}/api/v1/balances?address=${encodeURIComponent(s.short_address)}`,{headers:{"X-Contractless-Address":s.short_address,"X-Contractless-Public-Key":s.public_key,"X-Contractless-Signature":h}}),p=await w.json().catch(()=>{});if(!w.ok||(p==null?void 0:p.success)!==!0)throw new Error((p==null?void 0:p.error)??`Balance lookup failed with HTTP ${w.status}.`);return await b(),p.data}if(o==="contractless_disconnect"){const c=await N(n,r),h=(await Q()).filter(w=>!(w.origin===c.origin&&w.appId===c.appId&&w.accessKey===c.accessKey));return await pt(h),{disconnected:!0}}if(o==="contractless_completeDualTransaction"){await N(n,r);const c=z(n.transaction);return JSON.parse(a.complete_dual_transaction_request(JSON.stringify(c),String(n.signature1??""),String(n.publicKey1??""),String(n.signature2??""),String(n.publicKey2??"")))}if(!["contractless_signMessage","contractless_sendTransaction","contractless_signDualTransaction"].includes(o))throw new Error("The website requested an unsupported wallet method.");if(await N(n,r),o==="contractless_sendTransaction"){const c=_t(n.transaction);await rt(a,c)}else if(o==="contractless_signDualTransaction"){const c=z(n.transaction);await rt(a,c)}const u={id:crypto.randomUUID(),method:o,params:n,origin:r,createdAt:Date.now(),risk:st(o,n),display:o==="contractless_signMessage"?{request:"Sign a text message",application_id:C(n.appId),website:r,message:ft(n.message),warning:"This is a text signature. It cannot move wallet assets."}:o==="contractless_signDualTransaction"?(()=>{const c=JSON.parse(a.inspect_transaction_request(JSON.stringify(n.transaction)));return{application_id:C(n.appId),website:r,transaction_type:c.transaction_name,signer_slot:n.signerSlot,transaction_fields:c.review,action:"Sign and return this signature to the application without broadcasting."}})():(()=>{const c=JSON.parse(a.inspect_transaction_request(JSON.stringify(n.transaction)));return{application_id:C(n.appId),website:r,transaction_type:c.transaction_name,transaction_fields:c.review,action:"Sign and broadcast this transaction."}})()};if(await ot(u),!await nt(u.id))throw new Error("The wallet request was rejected.");return it(a,u)}case"pending-provider-approval":{const r=await B(),o=r[0]??"";if(!o)return null;const n=`approval:${o}`,c=(await chrome.storage.session.get(n))[n];return c?s?(c.method==="contractless_connect"&&(c.params={...c.params,walletSessionId:s.sessionId},c.display={...c.display??{},wallet_address:s.short_address},await chrome.storage.session.set({[n]:c})),{locked:!1,request:c,position:1,total:r.length}):{locked:!0}:(await G(o),null)}case"resolve-provider-approval":{if(!s)throw new Error("Unlock the wallet before approving this request.");const r=String(e.id??""),o=await B();if(!r||o[0]!==r)throw new Error("The wallet approval request has expired.");const n=`approval:${r}`,c=(await chrome.storage.session.get(n))[n];if(!c)throw new Error("The wallet approval request has expired.");return c.method==="contractless_connect"&&(c.params={...c.params,walletSessionId:s.sessionId},await chrome.storage.session.set({[n]:c})),await chrome.storage.session.set({[`approval-result:${r}`]:{approved:e.approved===!0}}),await chrome.storage.session.remove(n),{resolved:!0,remaining:(await G(r)).length}}default:throw new Error("Unsupported wallet request.")}}chrome.runtime.onMessage.addListener((e,t,a)=>(It(e,t).then(i=>a({ok:!0,result:i})).catch(i=>a({ok:!1,error:i instanceof Error?i.message:String(i)})),!0));chrome.alarms.onAlarm.addListener(e=>{e.name===L&&R()}); diff --git a/extension/dist/chrome/manifest.json b/extension/dist/chrome/manifest.json index c42233e..c9aa099 100644 --- a/extension/dist/chrome/manifest.json +++ b/extension/dist/chrome/manifest.json @@ -6,7 +6,7 @@ "content_security_policy": { "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'" }, - "permissions": ["storage", "alarms", "activeTab", "clipboardWrite"], + "permissions": ["storage", "alarms", "clipboardWrite"], "host_permissions": ["https://api.contractless.dev/*"], "optional_host_permissions": ["https://*/"], "action": { diff --git a/extension/dist/chrome/popup.html b/extension/dist/chrome/popup.html index 1aaf6fa..4350f86 100644 --- a/extension/dist/chrome/popup.html +++ b/extension/dist/chrome/popup.html @@ -7,7 +7,7 @@ - +
diff --git a/extension/dist/chrome/popup.js b/extension/dist/chrome/popup.js index f57b0b4..769a04a 100644 --- a/extension/dist/chrome/popup.js +++ b/extension/dist/chrome/popup.js @@ -1,8 +1,8 @@ -import"./chunks/modulepreload-polyfill-B5Qt9EMX.js";import{c as Yt}from"./chunks/core-D2IK1U91.js";function Cn(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var de={},De,Ct;function En(){return Ct||(Ct=1,De=function(){return typeof Promise=="function"&&Promise.prototype&&Promise.prototype.then}),De}var Ue={},ee={},Et;function se(){if(Et)return ee;Et=1;let e;const t=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706];return ee.getSymbolSize=function(o){if(!o)throw new Error('"version" cannot be null or undefined');if(o<1||o>40)throw new Error('"version" should be in range from 1 to 40');return o*4+17},ee.getSymbolTotalCodewords=function(o){return t[o]},ee.getBCHDigit=function(n){let o=0;for(;n!==0;)o++,n>>>=1;return o},ee.setToSJISFunction=function(o){if(typeof o!="function")throw new Error('"toSJISFunc" is not a valid function.');e=o},ee.isKanjiModeEnabled=function(){return typeof e<"u"},ee.toSJIS=function(o){return e(o)},ee}var qe={},bt;function lt(){return bt||(bt=1,(function(e){e.L={bit:1},e.M={bit:0},e.Q={bit:3},e.H={bit:2};function t(n){if(typeof n!="string")throw new Error("Param is not a string");switch(n.toLowerCase()){case"l":case"low":return e.L;case"m":case"medium":return e.M;case"q":case"quartile":return e.Q;case"h":case"high":return e.H;default:throw new Error("Unknown EC Level: "+n)}}e.isValid=function(o){return o&&typeof o.bit<"u"&&o.bit>=0&&o.bit<4},e.from=function(o,r){if(e.isValid(o))return o;try{return t(o)}catch{return r}}})(qe)),qe}var Fe,kt;function bn(){if(kt)return Fe;kt=1;function e(){this.buffer=[],this.length=0}return e.prototype={get:function(t){const n=Math.floor(t/8);return(this.buffer[n]>>>7-t%8&1)===1},put:function(t,n){for(let o=0;o>>n-o-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(t){const n=Math.floor(this.length/8);this.buffer.length<=n&&this.buffer.push(0),t&&(this.buffer[n]|=128>>>this.length%8),this.length++}},Fe=e,Fe}var Ve,At;function kn(){if(At)return Ve;At=1;function e(t){if(!t||t<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=t,this.data=new Uint8Array(t*t),this.reservedBit=new Uint8Array(t*t)}return e.prototype.set=function(t,n,o,r){const i=t*this.size+n;this.data[i]=o,r&&(this.reservedBit[i]=!0)},e.prototype.get=function(t,n){return this.data[t*this.size+n]},e.prototype.xor=function(t,n,o){this.data[t*this.size+n]^=o},e.prototype.isReserved=function(t,n){return this.reservedBit[t*this.size+n]},Ve=e,Ve}var Ke={},Nt;function An(){return Nt||(Nt=1,(function(e){const t=se().getSymbolSize;e.getRowColCoords=function(o){if(o===1)return[];const r=Math.floor(o/7)+2,i=t(o),a=i===145?26:Math.ceil((i-13)/(2*r-2))*2,l=[i-7];for(let s=1;s=0&&r<=7},e.from=function(r){return e.isValid(r)?parseInt(r,10):void 0},e.getPenaltyN1=function(r){const i=r.size;let a=0,l=0,s=0,d=null,u=null;for(let m=0;m=5&&(a+=t.N1+(l-5)),d=f,l=1),f=r.get(p,m),f===u?s++:(s>=5&&(a+=t.N1+(s-5)),u=f,s=1)}l>=5&&(a+=t.N1+(l-5)),s>=5&&(a+=t.N1+(s-5))}return a},e.getPenaltyN2=function(r){const i=r.size;let a=0;for(let l=0;l=10&&(l===1488||l===93)&&a++,s=s<<1&2047|r.get(u,d),u>=10&&(s===1488||s===93)&&a++}return a*t.N3},e.getPenaltyN4=function(r){let i=0;const a=r.data.length;for(let s=0;s=0;){const a=i[0];for(let s=0;s0){const l=new Uint8Array(this.degree);return l.set(i,a),l}return i},Je=t,Je}var We={},He={},Ye={},Rt;function Qt(){return Rt||(Rt=1,Ye.isValid=function(t){return!isNaN(t)&&t>=1&&t<=40}),Ye}var O={},It;function Zt(){if(It)return O;It=1;const e="[0-9]+",t="[A-Z $%*+\\-./:]+";let n="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";n=n.replace(/u/g,"\\u");const o="(?:(?![A-Z0-9 $%*+\\-./:]|"+n+`)(?:.|[\r -]))+`;O.KANJI=new RegExp(n,"g"),O.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g"),O.BYTE=new RegExp(o,"g"),O.NUMERIC=new RegExp(e,"g"),O.ALPHANUMERIC=new RegExp(t,"g");const r=new RegExp("^"+n+"$"),i=new RegExp("^"+e+"$"),a=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");return O.testKanji=function(s){return r.test(s)},O.testNumeric=function(s){return i.test(s)},O.testAlphanumeric=function(s){return a.test(s)},O}var Pt;function ce(){return Pt||(Pt=1,(function(e){const t=Qt(),n=Zt();e.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]},e.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]},e.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]},e.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]},e.MIXED={bit:-1},e.getCharCountIndicator=function(i,a){if(!i.ccBits)throw new Error("Invalid mode: "+i);if(!t.isValid(a))throw new Error("Invalid version: "+a);return a>=1&&a<10?i.ccBits[0]:a<27?i.ccBits[1]:i.ccBits[2]},e.getBestModeForData=function(i){return n.testNumeric(i)?e.NUMERIC:n.testAlphanumeric(i)?e.ALPHANUMERIC:n.testKanji(i)?e.KANJI:e.BYTE},e.toString=function(i){if(i&&i.id)return i.id;throw new Error("Invalid mode")},e.isValid=function(i){return i&&i.bit&&i.ccBits};function o(r){if(typeof r!="string")throw new Error("Param is not a string");switch(r.toLowerCase()){case"numeric":return e.NUMERIC;case"alphanumeric":return e.ALPHANUMERIC;case"kanji":return e.KANJI;case"byte":return e.BYTE;default:throw new Error("Unknown mode: "+r)}}e.from=function(i,a){if(e.isValid(i))return i;try{return o(i)}catch{return a}}})(He)),He}var Mt;function Bn(){return Mt||(Mt=1,(function(e){const t=se(),n=Gt(),o=lt(),r=ce(),i=Qt(),a=7973,l=t.getBCHDigit(a);function s(p,f,h){for(let w=1;w<=40;w++)if(f<=e.getCapacity(w,h,p))return w}function d(p,f){return r.getCharCountIndicator(p,f)+4}function u(p,f){let h=0;return p.forEach(function(w){const R=d(w.mode,f);h+=R+w.getBitsLength()}),h}function m(p,f){for(let h=1;h<=40;h++)if(u(p,h)<=e.getCapacity(h,f,r.MIXED))return h}e.from=function(f,h){return i.isValid(f)?parseInt(f,10):h},e.getCapacity=function(f,h,w){if(!i.isValid(f))throw new Error("Invalid QR Code version");typeof w>"u"&&(w=r.BYTE);const R=t.getSymbolTotalCodewords(f),C=n.getTotalCodewordsCount(f,h),B=(R-C)*8;if(w===r.MIXED)return B;const E=B-d(w,f);switch(w){case r.NUMERIC:return Math.floor(E/10*3);case r.ALPHANUMERIC:return Math.floor(E/11*2);case r.KANJI:return Math.floor(E/13);case r.BYTE:default:return Math.floor(E/8)}},e.getBestVersionForData=function(f,h){let w;const R=o.from(h,o.M);if(Array.isArray(f)){if(f.length>1)return m(f,R);if(f.length===0)return 1;w=f[0]}else w=f;return s(w.mode,w.getLength(),R)},e.getEncodedBits=function(f){if(!i.isValid(f)||f<7)throw new Error("Invalid QR Code version");let h=f<<12;for(;t.getBCHDigit(h)-l>=0;)h^=a<=0;)s^=t<0&&(i=this.data.substr(r),a=parseInt(i,10),o.put(a,l*3+1))},Ze=t,Ze}var Xe,Ut;function In(){if(Ut)return Xe;Ut=1;const e=ce(),t=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function n(o){this.mode=e.ALPHANUMERIC,this.data=o}return n.getBitsLength=function(r){return 11*Math.floor(r/2)+6*(r%2)},n.prototype.getLength=function(){return this.data.length},n.prototype.getBitsLength=function(){return n.getBitsLength(this.data.length)},n.prototype.write=function(r){let i;for(i=0;i+2<=this.data.length;i+=2){let a=t.indexOf(this.data[i])*45;a+=t.indexOf(this.data[i+1]),r.put(a,11)}this.data.length%2&&r.put(t.indexOf(this.data[i]),6)},Xe=n,Xe}var et,qt;function Pn(){if(qt)return et;qt=1;const e=ce();function t(n){this.mode=e.BYTE,typeof n=="string"?this.data=new TextEncoder().encode(n):this.data=new Uint8Array(n)}return t.getBitsLength=function(o){return o*8},t.prototype.getLength=function(){return this.data.length},t.prototype.getBitsLength=function(){return t.getBitsLength(this.data.length)},t.prototype.write=function(n){for(let o=0,r=this.data.length;o=33088&&i<=40956)i-=33088;else if(i>=57408&&i<=60351)i-=49472;else throw new Error("Invalid SJIS character: "+this.data[r]+` -Make sure your charset is UTF-8`);i=(i>>>8&255)*192+(i&255),o.put(i,13)}},tt=n,tt}var nt={exports:{}},Vt;function $n(){return Vt||(Vt=1,(function(e){var t={single_source_shortest_paths:function(n,o,r){var i={},a={};a[o]=0;var l=t.PriorityQueue.make();l.push(o,0);for(var s,d,u,m,p,f,h,w,R;!l.empty();){s=l.pop(),d=s.value,m=s.cost,p=n[d]||{};for(u in p)p.hasOwnProperty(u)&&(f=p[u],h=m+f,w=a[u],R=typeof a[u]>"u",(R||w>h)&&(a[u]=h,l.push(u,h),i[u]=d))}if(typeof r<"u"&&typeof a[r]>"u"){var C=["Could not find a path from ",o," to ",r,"."].join("");throw new Error(C)}return i},extract_shortest_path_from_predecessor_list:function(n,o){for(var r=[],i=o;i;)r.push(i),n[i],i=n[i];return r.reverse(),r},find_path:function(n,o,r){var i=t.single_source_shortest_paths(n,o,r);return t.extract_shortest_path_from_predecessor_list(i,r)},PriorityQueue:{make:function(n){var o=t.PriorityQueue,r={},i;n=n||{};for(i in o)o.hasOwnProperty(i)&&(r[i]=o[i]);return r.queue=[],r.sorter=n.sorter||o.default_sorter,r},default_sorter:function(n,o){return n.cost-o.cost},push:function(n,o){var r={value:n,cost:o};this.queue.push(r),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};e.exports=t})(nt)),nt.exports}var Kt;function Dn(){return Kt||(Kt=1,(function(e){const t=ce(),n=Rn(),o=In(),r=Pn(),i=Mn(),a=Zt(),l=se(),s=$n();function d(C){return unescape(encodeURIComponent(C)).length}function u(C,B,E){const L=[];let D;for(;(D=C.exec(E))!==null;)L.push({data:D[0],index:D.index,mode:B,length:D[0].length});return L}function m(C){const B=u(a.NUMERIC,t.NUMERIC,C),E=u(a.ALPHANUMERIC,t.ALPHANUMERIC,C);let L,D;return l.isKanjiModeEnabled()?(L=u(a.BYTE,t.BYTE,C),D=u(a.KANJI,t.KANJI,C)):(L=u(a.BYTE_KANJI,t.BYTE,C),D=[]),B.concat(E,L,D).sort(function(N,A){return N.index-A.index}).map(function(N){return{data:N.data,mode:N.mode,length:N.length}})}function p(C,B){switch(B){case t.NUMERIC:return n.getBitsLength(C);case t.ALPHANUMERIC:return o.getBitsLength(C);case t.KANJI:return i.getBitsLength(C);case t.BYTE:return r.getBitsLength(C)}}function f(C){return C.reduce(function(B,E){const L=B.length-1>=0?B[B.length-1]:null;return L&&L.mode===E.mode?(B[B.length-1].data+=E.data,B):(B.push(E),B)},[])}function h(C){const B=[];for(let E=0;E=0&&k<=6&&(_===0||_===6)||_>=0&&_<=6&&(k===0||k===6)||k>=2&&k<=4&&_>=2&&_<=4?y.set(b+k,S+_,!0,!0):y.set(b+k,S+_,!1,!0))}}function h(y){const N=y.size;for(let A=8;A>k&1)===1,y.set(T,b,S,!0),y.set(b,T,S,!0)}function C(y,N,A){const v=y.size,T=u.getEncodedBits(N,A);let b,S;for(b=0;b<15;b++)S=(T>>b&1)===1,b<6?y.set(b,8,S,!0):b<8?y.set(b+1,8,S,!0):y.set(v-15+b,8,S,!0),b<8?y.set(8,v-b-1,S,!0):b<9?y.set(8,15-b-1+1,S,!0):y.set(8,15-b-1,S,!0);y.set(v-8,8,1,!0)}function B(y,N){const A=y.size;let v=-1,T=A-1,b=7,S=0;for(let k=A-1;k>0;k-=2)for(k===6&&k--;;){for(let _=0;_<2;_++)if(!y.isReserved(T,k-_)){let X=!1;S>>b&1)===1),y.set(T,k-_,X),b--,b===-1&&(S++,b=7)}if(T+=v,T<0||A<=T){T-=v,v=-v;break}}}function E(y,N,A){const v=new n;A.forEach(function(_){v.put(_.mode.bit,4),v.put(_.getLength(),m.getCharCountIndicator(_.mode,y)),_.write(v)});const T=e.getSymbolTotalCodewords(y),b=l.getTotalCodewordsCount(y,N),S=(T-b)*8;for(v.getLengthInBits()+4<=S&&v.put(0,4);v.getLengthInBits()%8!==0;)v.putBit(0);const k=(S-v.getLengthInBits())/8;for(let _=0;_40)throw new Error('"version" should be in range from 1 to 40');return o*4+17},ee.getSymbolTotalCodewords=function(o){return t[o]},ee.getBCHDigit=function(n){let o=0;for(;n!==0;)o++,n>>>=1;return o},ee.setToSJISFunction=function(o){if(typeof o!="function")throw new Error('"toSJISFunc" is not a valid function.');e=o},ee.isKanjiModeEnabled=function(){return typeof e<"u"},ee.toSJIS=function(o){return e(o)},ee}var qe={},kt;function dt(){return kt||(kt=1,(function(e){e.L={bit:1},e.M={bit:0},e.Q={bit:3},e.H={bit:2};function t(n){if(typeof n!="string")throw new Error("Param is not a string");switch(n.toLowerCase()){case"l":case"low":return e.L;case"m":case"medium":return e.M;case"q":case"quartile":return e.Q;case"h":case"high":return e.H;default:throw new Error("Unknown EC Level: "+n)}}e.isValid=function(o){return o&&typeof o.bit<"u"&&o.bit>=0&&o.bit<4},e.from=function(o,r){if(e.isValid(o))return o;try{return t(o)}catch{return r}}})(qe)),qe}var Fe,At;function An(){if(At)return Fe;At=1;function e(){this.buffer=[],this.length=0}return e.prototype={get:function(t){const n=Math.floor(t/8);return(this.buffer[n]>>>7-t%8&1)===1},put:function(t,n){for(let o=0;o>>n-o-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(t){const n=Math.floor(this.length/8);this.buffer.length<=n&&this.buffer.push(0),t&&(this.buffer[n]|=128>>>this.length%8),this.length++}},Fe=e,Fe}var Ve,Nt;function Nn(){if(Nt)return Ve;Nt=1;function e(t){if(!t||t<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=t,this.data=new Uint8Array(t*t),this.reservedBit=new Uint8Array(t*t)}return e.prototype.set=function(t,n,o,r){const i=t*this.size+n;this.data[i]=o,r&&(this.reservedBit[i]=!0)},e.prototype.get=function(t,n){return this.data[t*this.size+n]},e.prototype.xor=function(t,n,o){this.data[t*this.size+n]^=o},e.prototype.isReserved=function(t,n){return this.reservedBit[t*this.size+n]},Ve=e,Ve}var Ke={},St;function Sn(){return St||(St=1,(function(e){const t=se().getSymbolSize;e.getRowColCoords=function(o){if(o===1)return[];const r=Math.floor(o/7)+2,i=t(o),a=i===145?26:Math.ceil((i-13)/(2*r-2))*2,l=[i-7];for(let s=1;s=0&&r<=7},e.from=function(r){return e.isValid(r)?parseInt(r,10):void 0},e.getPenaltyN1=function(r){const i=r.size;let a=0,l=0,s=0,d=null,u=null;for(let f=0;f=5&&(a+=t.N1+(l-5)),d=p,l=1),p=r.get(g,f),p===u?s++:(s>=5&&(a+=t.N1+(s-5)),u=p,s=1)}l>=5&&(a+=t.N1+(l-5)),s>=5&&(a+=t.N1+(s-5))}return a},e.getPenaltyN2=function(r){const i=r.size;let a=0;for(let l=0;l=10&&(l===1488||l===93)&&a++,s=s<<1&2047|r.get(u,d),u>=10&&(s===1488||s===93)&&a++}return a*t.N3},e.getPenaltyN4=function(r){let i=0;const a=r.data.length;for(let s=0;s=0;){const a=i[0];for(let s=0;s0){const l=new Uint8Array(this.degree);return l.set(i,a),l}return i},Je=t,Je}var We={},He={},Ye={},It;function Zt(){return It||(It=1,Ye.isValid=function(t){return!isNaN(t)&&t>=1&&t<=40}),Ye}var O={},Pt;function Xt(){if(Pt)return O;Pt=1;const e="[0-9]+",t="[A-Z $%*+\\-./:]+";let n="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";n=n.replace(/u/g,"\\u");const o="(?:(?![A-Z0-9 $%*+\\-./:]|"+n+`)(?:.|[\r +]))+`;O.KANJI=new RegExp(n,"g"),O.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g"),O.BYTE=new RegExp(o,"g"),O.NUMERIC=new RegExp(e,"g"),O.ALPHANUMERIC=new RegExp(t,"g");const r=new RegExp("^"+n+"$"),i=new RegExp("^"+e+"$"),a=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");return O.testKanji=function(s){return r.test(s)},O.testNumeric=function(s){return i.test(s)},O.testAlphanumeric=function(s){return a.test(s)},O}var Mt;function ce(){return Mt||(Mt=1,(function(e){const t=Zt(),n=Xt();e.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]},e.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]},e.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]},e.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]},e.MIXED={bit:-1},e.getCharCountIndicator=function(i,a){if(!i.ccBits)throw new Error("Invalid mode: "+i);if(!t.isValid(a))throw new Error("Invalid version: "+a);return a>=1&&a<10?i.ccBits[0]:a<27?i.ccBits[1]:i.ccBits[2]},e.getBestModeForData=function(i){return n.testNumeric(i)?e.NUMERIC:n.testAlphanumeric(i)?e.ALPHANUMERIC:n.testKanji(i)?e.KANJI:e.BYTE},e.toString=function(i){if(i&&i.id)return i.id;throw new Error("Invalid mode")},e.isValid=function(i){return i&&i.bit&&i.ccBits};function o(r){if(typeof r!="string")throw new Error("Param is not a string");switch(r.toLowerCase()){case"numeric":return e.NUMERIC;case"alphanumeric":return e.ALPHANUMERIC;case"kanji":return e.KANJI;case"byte":return e.BYTE;default:throw new Error("Unknown mode: "+r)}}e.from=function(i,a){if(e.isValid(i))return i;try{return o(i)}catch{return a}}})(He)),He}var $t;function xn(){return $t||($t=1,(function(e){const t=se(),n=Qt(),o=dt(),r=ce(),i=Zt(),a=7973,l=t.getBCHDigit(a);function s(g,p,h){for(let w=1;w<=40;w++)if(p<=e.getCapacity(w,h,g))return w}function d(g,p){return r.getCharCountIndicator(g,p)+4}function u(g,p){let h=0;return g.forEach(function(w){const x=d(w.mode,p);h+=x+w.getBitsLength()}),h}function f(g,p){for(let h=1;h<=40;h++)if(u(g,h)<=e.getCapacity(h,p,r.MIXED))return h}e.from=function(p,h){return i.isValid(p)?parseInt(p,10):h},e.getCapacity=function(p,h,w){if(!i.isValid(p))throw new Error("Invalid QR Code version");typeof w>"u"&&(w=r.BYTE);const x=t.getSymbolTotalCodewords(p),C=n.getTotalCodewordsCount(p,h),B=(x-C)*8;if(w===r.MIXED)return B;const E=B-d(w,p);switch(w){case r.NUMERIC:return Math.floor(E/10*3);case r.ALPHANUMERIC:return Math.floor(E/11*2);case r.KANJI:return Math.floor(E/13);case r.BYTE:default:return Math.floor(E/8)}},e.getBestVersionForData=function(p,h){let w;const x=o.from(h,o.M);if(Array.isArray(p)){if(p.length>1)return f(p,x);if(p.length===0)return 1;w=p[0]}else w=p;return s(w.mode,w.getLength(),x)},e.getEncodedBits=function(p){if(!i.isValid(p)||p<7)throw new Error("Invalid QR Code version");let h=p<<12;for(;t.getBCHDigit(h)-l>=0;)h^=a<=0;)s^=t<0&&(i=this.data.substr(r),a=parseInt(i,10),o.put(a,l*3+1))},Ze=t,Ze}var Xe,qt;function Mn(){if(qt)return Xe;qt=1;const e=ce(),t=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function n(o){this.mode=e.ALPHANUMERIC,this.data=o}return n.getBitsLength=function(r){return 11*Math.floor(r/2)+6*(r%2)},n.prototype.getLength=function(){return this.data.length},n.prototype.getBitsLength=function(){return n.getBitsLength(this.data.length)},n.prototype.write=function(r){let i;for(i=0;i+2<=this.data.length;i+=2){let a=t.indexOf(this.data[i])*45;a+=t.indexOf(this.data[i+1]),r.put(a,11)}this.data.length%2&&r.put(t.indexOf(this.data[i]),6)},Xe=n,Xe}var et,Ft;function $n(){if(Ft)return et;Ft=1;const e=ce();function t(n){this.mode=e.BYTE,typeof n=="string"?this.data=new TextEncoder().encode(n):this.data=new Uint8Array(n)}return t.getBitsLength=function(o){return o*8},t.prototype.getLength=function(){return this.data.length},t.prototype.getBitsLength=function(){return t.getBitsLength(this.data.length)},t.prototype.write=function(n){for(let o=0,r=this.data.length;o=33088&&i<=40956)i-=33088;else if(i>=57408&&i<=60351)i-=49472;else throw new Error("Invalid SJIS character: "+this.data[r]+` +Make sure your charset is UTF-8`);i=(i>>>8&255)*192+(i&255),o.put(i,13)}},tt=n,tt}var nt={exports:{}},Kt;function Dn(){return Kt||(Kt=1,(function(e){var t={single_source_shortest_paths:function(n,o,r){var i={},a={};a[o]=0;var l=t.PriorityQueue.make();l.push(o,0);for(var s,d,u,f,g,p,h,w,x;!l.empty();){s=l.pop(),d=s.value,f=s.cost,g=n[d]||{};for(u in g)g.hasOwnProperty(u)&&(p=g[u],h=f+p,w=a[u],x=typeof a[u]>"u",(x||w>h)&&(a[u]=h,l.push(u,h),i[u]=d))}if(typeof r<"u"&&typeof a[r]>"u"){var C=["Could not find a path from ",o," to ",r,"."].join("");throw new Error(C)}return i},extract_shortest_path_from_predecessor_list:function(n,o){for(var r=[],i=o;i;)r.push(i),n[i],i=n[i];return r.reverse(),r},find_path:function(n,o,r){var i=t.single_source_shortest_paths(n,o,r);return t.extract_shortest_path_from_predecessor_list(i,r)},PriorityQueue:{make:function(n){var o=t.PriorityQueue,r={},i;n=n||{};for(i in o)o.hasOwnProperty(i)&&(r[i]=o[i]);return r.queue=[],r.sorter=n.sorter||o.default_sorter,r},default_sorter:function(n,o){return n.cost-o.cost},push:function(n,o){var r={value:n,cost:o};this.queue.push(r),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};e.exports=t})(nt)),nt.exports}var jt;function qn(){return jt||(jt=1,(function(e){const t=ce(),n=Pn(),o=Mn(),r=$n(),i=Un(),a=Xt(),l=se(),s=Dn();function d(C){return unescape(encodeURIComponent(C)).length}function u(C,B,E){const L=[];let U;for(;(U=C.exec(E))!==null;)L.push({data:U[0],index:U.index,mode:B,length:U[0].length});return L}function f(C){const B=u(a.NUMERIC,t.NUMERIC,C),E=u(a.ALPHANUMERIC,t.ALPHANUMERIC,C);let L,U;return l.isKanjiModeEnabled()?(L=u(a.BYTE,t.BYTE,C),U=u(a.KANJI,t.KANJI,C)):(L=u(a.BYTE_KANJI,t.BYTE,C),U=[]),B.concat(E,L,U).sort(function(N,A){return N.index-A.index}).map(function(N){return{data:N.data,mode:N.mode,length:N.length}})}function g(C,B){switch(B){case t.NUMERIC:return n.getBitsLength(C);case t.ALPHANUMERIC:return o.getBitsLength(C);case t.KANJI:return i.getBitsLength(C);case t.BYTE:return r.getBitsLength(C)}}function p(C){return C.reduce(function(B,E){const L=B.length-1>=0?B[B.length-1]:null;return L&&L.mode===E.mode?(B[B.length-1].data+=E.data,B):(B.push(E),B)},[])}function h(C){const B=[];for(let E=0;E=0&&k<=6&&(_===0||_===6)||_>=0&&_<=6&&(k===0||k===6)||k>=2&&k<=4&&_>=2&&_<=4?y.set(b+k,S+_,!0,!0):y.set(b+k,S+_,!1,!0))}}function h(y){const N=y.size;for(let A=8;A>k&1)===1,y.set(T,b,S,!0),y.set(b,T,S,!0)}function C(y,N,A){const v=y.size,T=u.getEncodedBits(N,A);let b,S;for(b=0;b<15;b++)S=(T>>b&1)===1,b<6?y.set(b,8,S,!0):b<8?y.set(b+1,8,S,!0):y.set(v-15+b,8,S,!0),b<8?y.set(8,v-b-1,S,!0):b<9?y.set(8,15-b-1+1,S,!0):y.set(8,15-b-1,S,!0);y.set(v-8,8,1,!0)}function B(y,N){const A=y.size;let v=-1,T=A-1,b=7,S=0;for(let k=A-1;k>0;k-=2)for(k===6&&k--;;){for(let _=0;_<2;_++)if(!y.isReserved(T,k-_)){let X=!1;S>>b&1)===1),y.set(T,k-_,X),b--,b===-1&&(S++,b=7)}if(T+=v,T<0||A<=T){T-=v,v=-v;break}}}function E(y,N,A){const v=new n;A.forEach(function(_){v.put(_.mode.bit,4),v.put(_.getLength(),f.getCharCountIndicator(_.mode,y)),_.write(v)});const T=e.getSymbolTotalCodewords(y),b=l.getTotalCodewordsCount(y,N),S=(T-b)*8;for(v.getLengthInBits()+4<=S&&v.put(0,4);v.getLengthInBits()%8!==0;)v.putBit(0);const k=(S-v.getLengthInBits())/8;for(let _=0;_=7&&R(_,N),B(_,S),isNaN(v)&&(v=a.getBestMask(_,C.bind(null,_,A))),a.applyMask(v,_),C(_,A,v),{modules:_,version:N,errorCorrectionLevel:A,maskPattern:v,segments:T}}return Ue.create=function(N,A){if(typeof N>"u"||N==="")throw new Error("No input text");let v=t.M,T,b;return typeof A<"u"&&(v=t.from(A.errorCorrectionLevel,t.M),T=d.from(A.version),b=a.from(A.maskPattern),A.toSJISFunc&&e.setToSJISFunction(A.toSJISFunc)),D(N,T,v,b)},Ue}var rt={},ot={},zt;function Xt(){return zt||(zt=1,(function(e){function t(n){if(typeof n=="number"&&(n=n.toString()),typeof n!="string")throw new Error("Color should be defined as hex string");let o=n.slice().replace("#","").split("");if(o.length<3||o.length===5||o.length>8)throw new Error("Invalid hex color: "+n);(o.length===3||o.length===4)&&(o=Array.prototype.concat.apply([],o.map(function(i){return[i,i]}))),o.length===6&&o.push("F","F");const r=parseInt(o.join(""),16);return{r:r>>24&255,g:r>>16&255,b:r>>8&255,a:r&255,hex:"#"+o.slice(0,6).join("")}}e.getOptions=function(o){o||(o={}),o.color||(o.color={});const r=typeof o.margin>"u"||o.margin===null||o.margin<0?4:o.margin,i=o.width&&o.width>=21?o.width:void 0,a=o.scale||4;return{width:i,scale:i?4:a,margin:r,color:{dark:t(o.color.dark||"#000000ff"),light:t(o.color.light||"#ffffffff")},type:o.type,rendererOpts:o.rendererOpts||{}}},e.getScale=function(o,r){return r.width&&r.width>=o+r.margin*2?r.width/(o+r.margin*2):r.scale},e.getImageWidth=function(o,r){const i=e.getScale(o,r);return Math.floor((o+r.margin*2)*i)},e.qrToImageData=function(o,r,i){const a=r.modules.size,l=r.modules.data,s=e.getScale(a,i),d=Math.floor((a+i.margin*2)*s),u=i.margin*s,m=[i.color.light,i.color.dark];for(let p=0;p=u&&f>=u&&p"u"&&(!a||!a.getContext)&&(s=a,a=void 0),a||(d=o()),s=t.getOptions(s);const u=t.getImageWidth(i.modules.size,s),m=d.getContext("2d"),p=m.createImageData(u,u);return t.qrToImageData(p.data,i,s),n(m,d,u),m.putImageData(p,0,0),d},e.renderToDataURL=function(i,a,l){let s=l;typeof s>"u"&&(!a||!a.getContext)&&(s=a,a=void 0),s||(s={});const d=e.render(i,a,s),u=s.type||"image/png",m=s.rendererOpts||{};return d.toDataURL(u,m.quality)}})(rt)),rt}var it={},Jt;function Fn(){if(Jt)return it;Jt=1;const e=Xt();function t(r,i){const a=r.a/255,l=i+'="'+r.hex+'"';return a<1?l+" "+i+'-opacity="'+a.toFixed(2).slice(1)+'"':l}function n(r,i,a){let l=r+i;return typeof a<"u"&&(l+=" "+a),l}function o(r,i,a){let l="",s=0,d=!1,u=0;for(let m=0;m0&&p>0&&r[m-1]||(l+=d?n("M",p+a,.5+f+a):n("m",s,0),s=0,d=!1),p+1':"",f="',h='viewBox="0 0 '+m+" "+m+'"',R=''+p+f+` -`;return typeof l=="function"&&l(null,R),R},it}var Wt;function Vn(){if(Wt)return de;Wt=1;const e=En(),t=Un(),n=qn(),o=Fn();function r(i,a,l,s,d){const u=[].slice.call(arguments,1),m=u.length,p=typeof u[m-1]=="function";if(!p&&!e())throw new Error("Callback required as last argument");if(p){if(m<2)throw new Error("Too few arguments provided");m===2?(d=l,l=a,a=s=void 0):m===3&&(a.getContext&&typeof d>"u"?(d=s,s=void 0):(d=s,s=l,l=a,a=void 0))}else{if(m<1)throw new Error("Too few arguments provided");return m===1?(l=a,a=s=void 0):m===2&&!a.getContext&&(s=l,l=a,a=void 0),new Promise(function(f,h){try{const w=t.create(l,s);f(i(w,a,s))}catch(w){h(w)}})}try{const f=t.create(l,s);d(null,i(f,a,s))}catch(f){d(f)}}return de.create=t.create,de.toCanvas=r.bind(null,n.render),de.toDataURL=r.bind(null,n.renderToDataURL),de.toString=r.bind(null,function(i,a,l){return o.render(i,l)}),de}var Kn=Vn();const jn=Cn(Kn),c=e=>document.getElementById(e),zn=Array.from(document.querySelectorAll(".screen")),M=c("notice"),en=navigator.userAgent.includes("Firefox");let Le="",fe="",ge="",ie="",g,dt,Te="held",K=1,ae=0;const we=8;let x,H=[],Z,P,_e,tn="activity",G,ve="",oe="";const he=20,On={1:"Mining Reward",2:"Transfer",3:"Token Creation",4:"NFT/RWA Creation",5:"Marketing",6:"Swap",7:"Loan",8:"Loan Payment",9:"Collateral Claim",10:"Asset Burn",11:"Token Issuance",12:"Vanity Address",100:"Storage Key",101:"Data Storage Bool",102:"Data Storage U8",103:"Data Storage U16",104:"Data Storage U32",105:"Data Storage U64",106:"Data Storage U128",107:"Data Storage String",108:"Data Storage I8",109:"Data Storage I16",110:"Data Storage I32",111:"Data Storage I64",112:"Data Storage I128",113:"Delete Stored Data",200:"Proposal",201:"Proposal Vote",202:"Activation Vote"};async function $(e,t={}){const n=await chrome.runtime.sendMessage({type:e,...t});if(!(n!=null&&n.ok))throw new Error((n==null?void 0:n.error)??"Wallet request failed.");return n.result}function I(e,t=!0){zn.forEach(n=>{n.hidden=n.id!==e}),t&&(M.textContent="")}function V(e){g=e;const t=e.networkName,n=e.networkSymbol;document.querySelectorAll("[data-network-name]").forEach(o=>{o.textContent=t}),document.querySelectorAll("[data-network-symbol]").forEach(o=>{o.textContent=n}),c("base-asset-name").textContent=`Contractless ${t}`,c("wallet-address").textContent=e.address??"",c("wallet-address-short").textContent=e.address?`${e.address.slice(0,6)}...${e.address.slice(-6)}`:"Account",c("settings-testnet-api-url").value=e.testnetApiUrl,c("settings-mainnet-api-url").value=e.mainnetApiUrl,document.querySelectorAll("[data-select-network]").forEach(o=>{const r=o.dataset.selectNetwork===e.selectedNetwork;o.classList.toggle("active",r),o.setAttribute("aria-pressed",String(r))}),c("settings-lock-timeout").value=String(e.autoLockMinutes),Xn(e),e.exists?e.unlocked?at().then(o=>{o||(I("dashboard-screen"),Be())}):I("locked-screen"):I("create-screen")}function Jn(e,t){return e==="contractless_connect"?"Connect application":e==="contractless_signMessage"?"Sign text message":e==="contractless_sendTransaction"||e==="contractless_signDualTransaction"?`Sign ${String(t.transaction_type??"transaction")}`:"Review request"}function j(e,t,n){const o=document.createElement("dt");o.textContent=t.replaceAll("_"," ");const r=document.createElement("dd");r.textContent=typeof n=="object"?JSON.stringify(n,null,2):String(n),e.append(o,r)}function te(e,t,n,o){const r=re(e[t]),i=String(e[n]??"").trim().toUpperCase(),a=Number(e[o]??0);return`${r} ${i}${a>0?` #${a}`:""}`}function Ht(e,t,n){const o=n===1?2:1,r=(g==null?void 0:g.networkSymbol)??"CLTC";j(e,"Your miner tip",te(t,`tip${n}`,`ticker${n}`,`nft_series${n}`)),j(e,"Your transaction fee",`${re(t[`txfee${n}`])} ${r}`),j(e,"Other party miner tip",te(t,`tip${o}`,`ticker${o}`,`nft_series${o}`)),j(e,"Other party transaction fee",`${re(t[`txfee${o}`])} ${r}`)}function Wn(e,t){var a;const n=((a=g==null?void 0:g.address)==null?void 0:a.trim().toLowerCase())??"",o=String(t.sender1??"").trim().toLowerCase(),r=String(t.sender2??"").trim().toLowerCase(),i=n===o?1:n===r?2:0;if(i===1){j(e,"Sending",te(t,"value1","ticker1","nft_series1")),j(e,"Receiving",te(t,"value2","ticker2","nft_series2")),Ht(e,t,1);return}if(i===2){j(e,"Sending",te(t,"value2","ticker2","nft_series2")),j(e,"Receiving",te(t,"value1","ticker1","nft_series1")),Ht(e,t,2);return}j(e,"First party sending",te(t,"value1","ticker1","nft_series1")),j(e,"Second party sending",te(t,"value2","ticker2","nft_series2"))}function ye(e){const t=c("approve-provider-approval"),n=c("reject-provider-approval"),o=e!==null;t.disabled=o,n.disabled=o,t.classList.toggle("is-processing",e==="approve"),n.classList.toggle("is-processing",e==="reject"),t.textContent=e==="approve"?"Processing...":"Approve",n.textContent=e==="reject"?"Rejecting...":"Reject"}async function at(){const e=await $("pending-provider-approval");if(!(e!=null&&e.request))return!1;const t=e.request;ye(null),oe=t.id;const n=(e.total??0)>1?` · Request ${e.position??1} of ${e.total}`:"";c("provider-approval-origin").textContent=`${t.origin}${n}`;const o=c("provider-approval-risk");o.className=`risk-label risk-${t.risk}`,o.textContent=t.risk==="safe"?"Safe":t.risk==="low"?"Low risk":"High risk";const r=t.display??{},i=t.method==="contractless_sendTransaction"||t.method==="contractless_signDualTransaction";c("provider-approval-title").textContent=Jn(t.method,r),c("provider-approval-intro").textContent=i?"Review every transaction field before signing.":"Review this request before approving it.";const a=c("provider-approval-details");return a.replaceChildren(),Object.entries(r).forEach(([l,s])=>{if(l==="transaction_fields"&&s&&typeof s=="object"){const d=s,u=Number(d.txtype??0),m=new Set(["ticker1","nft_series1","value1","ticker2","nft_series2","value2","tip1","tip2","txfee1","txfee2"]);u===6&&Wn(a,d),Object.entries(d).forEach(([p,f])=>{u===6&&m.has(p)||j(a,p==="txtype"?"transaction_type_id":p,dn(u,p,f))});return}j(a,l,s)}),I("provider-approval-screen"),!0}async function nn(e,t){if(!(e>0&&await at())){if(t){const n=Date.now()+1500;for(;Date.now()setTimeout(o,75))}}window.close()}}function Hn(e){return e.replace(/[.0]/g,"").length>0}function st(){const e=c("token-list");if(e.replaceChildren(),!x){const s=document.createElement("div");s.className="empty-assets";const d=document.createElement("strong");d.textContent="Loading token balances...";const u=document.createElement("span");u.textContent="Balances are retrieved from the selected Contractless API.",s.append(d,u),e.append(s);return}const t=(g==null?void 0:g.networkSymbol)??"CLTC",n=new Set(x.tokens.map(s=>s.token.trim().toUpperCase())),o=new Set(x.nfts.map(s=>`${s.name.trim().toUpperCase()}|${Number(s.series||0)}`)),r=x.balances.filter(s=>{const d=s.asset.trim().toUpperCase(),u=`${d}|${Number(s.nft_series||0)}`;return s.nft_series===0&&d!=="CLTC"&&d!=="CLC"&&n.has(d)&&!o.has(u)}),i=new Map(r.map(s=>[s.asset.trim().toUpperCase(),s])),a=Te==="all"?x.tokens.map(s=>s.token):r.filter(s=>Hn(s.balance)).map(s=>s.asset),l=[...new Set(a.map(s=>s.trim().toUpperCase()))].filter(s=>s!==t&&!o.has(`${s}|0`)).sort((s,d)=>s.localeCompare(d));if(l.length===0){const s=document.createElement("div");s.className="empty-assets";const d=document.createElement("strong");d.textContent=Te==="held"?"No token balances found":"No tokens found";const u=document.createElement("span");u.textContent=Te==="held"?"Switch to All tokens to view the complete network token list.":x.tokenCatalogError?`Token catalog unavailable: ${x.tokenCatalogError}`:"The selected API did not return any fungible tokens.",s.append(d,u),e.append(s);return}l.forEach(s=>{const d=i.get(s),u=document.createElement("div");u.className="asset-row";const m=document.createElement("div");m.className="asset-symbol token-symbol",m.textContent=s.slice(0,3);const p=document.createElement("div");p.className="asset-name";const f=document.createElement("strong");f.textContent=s;const h=document.createElement("span");h.textContent="Contractless token",p.append(f,h);const w=document.createElement("div");w.className="asset-value";const R=document.createElement("strong");R.textContent=(d==null?void 0:d.balance)??"0.00000000";const C=document.createElement("span");C.textContent=s,w.append(R,C),u.append(m,p,w),e.append(u)})}async function Be(){if(g!=null&&g.unlocked){x=void 0,c("base-balance").textContent="--",c("base-asset-balance").textContent="--",st();try{if(!g.apiUrl)throw new Error(`No ${g.networkName} API is configured.`);const e=await $("wallet-balances");x={balances:Array.isArray(e.balances)?e.balances:[],tokens:Array.isArray(e.tokens)?e.tokens:[],nfts:Array.isArray(e.nfts)?e.nfts:[],tokenCatalogError:e.tokenCatalogError,nftCatalogError:e.nftCatalogError};const t=g.networkSymbol,n=x.balances.find(r=>r.nft_series===0&&r.asset.toUpperCase()===t),o=(n==null?void 0:n.balance)??"0.00000000";c("base-balance").textContent=o,c("base-asset-balance").textContent=o,st()}catch(e){const t=c("token-list");t.replaceChildren();const n=document.createElement("div");n.className="empty-assets balance-error";const o=document.createElement("strong");o.textContent="Unable to load balances";const r=document.createElement("span");r.textContent=F(e),n.append(o,r),t.append(n),M.textContent=F(e)}}}function Ne(e,t){return`${e.trim().toUpperCase()}|${t}`}function Yn(e){try{return Y(e,"Balance")>0n}catch{return!1}}function rn(e){if(e.ownership_type!==1)return"Complete ownership";try{const t=Y(e.balance,"Balance"),n=Y(e.supply,"Supply");if(n<=0n)return"0% ownership";const o=t*100000000n/n,r=o/1000000n,i=(o%1000000n).toString().padStart(6,"0").replace(/0+$/,"");return`${r}${i?`.${i}`:""}% ownership`}catch{return"Fractional ownership"}}function ut(e){var t;return(t=e.details)!=null&&t.metadata&&typeof e.details.metadata=="object"?e.details.metadata:{}}function ft(e){const t=ut(e).name;return typeof t=="string"&&t.trim()?t.trim():e.series>0?`${e.name} #${e.series}`:e.name}function on(e){const n=ut(e).contractless;return n&&typeof n=="object"&&String(n.metadata_type??"").toLowerCase()==="rwa"?"RWA":"NFT"}function be(e){return e.series>0?`${e.name}_${e.series}`:e.name}function Gn(e,t=7,n=7){return e.length>t+n+3?`${e.slice(0,t)}...${e.slice(-n)}`:e}function Qn(e,t){var r;const n=document.createElement("div");if(n.className=t,(r=e.details)!=null&&r.image_data_url){const i=document.createElement("img");return i.src=e.details.image_data_url,i.alt=ft(e),n.append(i),n}const o=document.createElement("span");return o.textContent=e.loading?"...":e.name.slice(0,2).toUpperCase(),n.append(o),n}function an(){const e=(K-1)*we;return H.slice(e,e+we)}function Ce(){const e=c("nfts-list");e.replaceChildren();const t=Math.max(1,Math.ceil(H.length/we));if(K=Math.min(Math.max(1,K),t),c("nfts-count").textContent=H.length===1?"1 owned asset":`${H.length} owned assets`,c("nfts-page").textContent=String(K),c("nfts-pages").textContent=String(t),c("nfts-pagination").hidden=t<=1,c("nfts-previous").disabled=K<=1,c("nfts-next").disabled=K>=t,!H.length){const n=document.createElement("div");n.className="nfts-empty";const o=document.createElement("strong");o.textContent="No NFTs or RWAs found";const r=document.createElement("span");r.textContent=x!=null&&x.nftCatalogError?`NFT catalog unavailable: ${x.nftCatalogError}`:"Assets owned by this wallet will appear here.",n.append(o,r),e.append(n);return}an().forEach(n=>{const o=document.createElement("button");o.type="button",o.className="nft-card",o.append(Qn(n,"nft-card-media"));const r=document.createElement("div");r.className="nft-card-identity";const i=document.createElement("span");i.textContent=on(n);const a=document.createElement("strong");a.textContent=ft(n);const l=document.createElement("small");l.textContent=be(n);const s=document.createElement("b");if(s.textContent=rn(n),r.append(i,a,l,s),n.error){const d=document.createElement("em");d.textContent="Media unavailable",r.append(d)}o.append(r),o.addEventListener("click",()=>Zn(n)),e.append(o)})}function Se(e,t,n){const o=document.createElement("div"),r=document.createElement("dt");r.textContent=t;const i=document.createElement("dd");i.textContent=n||"--",o.append(r,i),e.append(o)}function xe(e){Z=e;const t=e.details,n=ut(e),o=on(e),r=ft(e);c("nft-detail-title").textContent=r,c("nft-detail-kind").textContent=`${o} details`,c("nft-detail-badge").textContent=o,c("nft-detail-name").textContent=r,c("nft-detail-ownership").textContent=rn(e);const i=c("nft-detail-image");i.src=(t==null?void 0:t.image_data_url)??"",i.alt=r,i.hidden=!(t!=null&&t.image_data_url);const a=n.description??n.summary;c("nft-detail-description").textContent=typeof a=="string"&&a.trim()?a.trim():t?"No description was included in the NFT metadata.":"Loading NFT metadata and provenance...";const l=c("nft-detail-attributes");l.replaceChildren(),(Array.isArray(n.attributes)?n.attributes.slice(0,12):[]).forEach(m=>{if(!m||typeof m!="object")return;const p=m,f=document.createElement("div"),h=document.createElement("span");h.textContent=String(p.trait_type??p.type??"Attribute");const w=document.createElement("strong");w.textContent=String(p.value??""),f.append(h,w),l.append(f)}),l.hidden=l.childElementCount===0;const d=c("nft-detail-fields");d.replaceChildren(),Se(d,"Asset",be(e)),Se(d,"Creator",(t==null?void 0:t.creator)??"--"),Se(d,"IPFS CID",(t==null?void 0:t.item_ipfs)??"--"),Se(d,"Origin transaction",(t==null?void 0:t.genesis_txid)??e.origin_txid);const u=c("nft-detail-history");if(u.replaceChildren(),t)if(t.history.length)t.history.slice().reverse().forEach(m=>{const p=document.createElement("button");p.type="button",p.className="nft-history-row",p.title=`View full transaction ${m.txid}`;const f=document.createElement("strong");f.textContent=m.action;const h=document.createElement("span");h.textContent=`Block ${Number(m.block).toLocaleString()}`;const w=document.createElement("small");w.textContent=Gn(m.txid),p.append(f,h,w),p.addEventListener("click",()=>{fn({txid:m.txid,block_height:Number(m.block),transaction_hex:""},"nft")}),u.append(p)});else{const m=document.createElement("p");m.textContent="No provenance records were returned.",u.append(m)}else{const m=document.createElement("p");m.textContent="Loading provenance...",u.append(m)}}function Zn(e){xe(e),I("nft-detail-screen")}async function mt(e){const t=an().filter(r=>!r.details&&!r.loading);let n=0;const o=async()=>{for(;n[Ne(r.name,r.series),r]));H=x.nfts.map(r=>{const i=x==null?void 0:x.balances.find(l=>Ne(l.asset,Number(l.nft_series||0))===Ne(r.name,Number(r.series||0)));if(!i||!Yn(i.balance))return null;const a=n.get(Ne(r.name,r.series));return{name:r.name.trim(),series:Number(r.series||0),origin_txid:r.origin_txid,ownership_type:Number(r.ownership_type||0),supply:r.supply,balance:i.balance,details:a==null?void 0:a.details,error:a==null?void 0:a.error}}).filter(r=>r!==null).sort((r,i)=>r.name.localeCompare(i.name)||r.series-i.series);const o=Math.max(1,Math.ceil(H.length/we));K=Math.min(K,o),Ce(),await mt(t)}function Xn(e){const t=c("known-addresses");t.replaceChildren(),e.wallets.forEach(n=>{const o=document.createElement("div");o.className=`known-address${n.active?" active-address":""}`;const r=document.createElement("button");r.type="button",r.className="address-select",r.dataset.walletId=n.id;const i=document.createElement("span");i.className="address-avatar";const a=document.createElement("img");a.src=chrome.runtime.getURL("contractless-logo.png"),a.alt="",i.append(a);const l=document.createElement("span");l.className="address-details";const s=document.createElement("strong");s.textContent=n.label;const d=document.createElement("small");d.textContent=n.address,l.append(s,d);const u=document.createElement("span");u.className="selected-mark",u.textContent=n.active?"✓":"",r.append(i,l,u),r.addEventListener("click",()=>{if(n.active){z(!1);return}U(async()=>{z(!1),fe="",ie="",V(await $("switch-wallet",{walletId:n.id}))})});const m=document.createElement("button");m.type="button",m.className="rename-address",m.title="Rename wallet",m.setAttribute("aria-label",`Rename ${n.label}`),m.textContent="✎",m.addEventListener("click",()=>{const p=window.prompt("Wallet label",n.label);p===null||p.trim()===n.label||U(async()=>{const f=await $("rename-wallet",{walletId:n.id,label:p});V(f),z(!0)})}),o.append(r,m),t.append(o)})}function z(e){const t=c("account-drawer"),n=c("drawer-backdrop"),o=c("account-menu-button");t.classList.toggle("open",e),t.setAttribute("aria-hidden",String(!e)),o.setAttribute("aria-expanded",String(e)),n.hidden=!e}function gt(){c("revealed-private-key").value="",c("private-key-result").hidden=!0}function Ee(e){if(c("backup-key-modal").hidden=!e,c("backup-key-backdrop").hidden=!e,e){const t=c("backup-key-input");t.value="",t.focus()}else c("backup-key-input").value="",dt=void 0}async function er(){const e=await $("wallet-receive-address"),t=String(e.receiveAddress??"");if(!t)throw new Error("No active wallet address is available.");c("receive-address-label").textContent=e.vanity?"Vanity address":"Wallet address",c("receive-address-value").textContent=t;const n=c("receive-qr");await jn.toCanvas(n,t,{width:220,margin:1,errorCorrectionLevel:"M",color:{dark:"#071016",light:"#ffffff"}}),I("receive-screen")}function Y(e,t){const n=e.trim();if(!/^(?:0|[1-9]\d*)(?:\.\d{1,8})?$/.test(n))throw new Error(`${t} must be a positive number with no more than 8 decimal places.`);const[o,r=""]=n.split(".");return BigInt(o)*100000000n+BigInt(r.padEnd(8,"0"))}function ne(e){const t=e/100000000n,n=(e%100000000n).toString().padStart(8,"0");return`${t}.${n}`}function sn(){if(P)return P.balance;const e=c("send-asset").value,t=x==null?void 0:x.balances.find(n=>n.nft_series===0&&n.asset.trim().toUpperCase()===e);return(t==null?void 0:t.balance)??"0.00000000"}function cn(){const e=c("send-asset").value,t=(g==null?void 0:g.networkSymbol)??"CLTC";if(e!==t)return 100000000n;const n=c("send-amount").value.trim();if(!n)return 0n;try{return(Y(n,"Amount")+99n)/100n}catch{return 0n}}function Re(){const e=(P==null?void 0:P.name)??c("send-asset").value,t=(g==null?void 0:g.networkSymbol)??"CLTC",n=P?be(P):e;c("send-amount-symbol").textContent=n,c("send-available").textContent=`Available: ${sn()} ${n}`;const o=cn();c("send-fee").value=ne(o),c("send-fee-note").textContent=!P&&e===t?"Minimum fee: 1% of the transfer amount.":`Minimum fee: 1 ${t} for asset transfers.`}function tr(){const e=c("send-asset");e.replaceChildren();const t=(g==null?void 0:g.networkSymbol)??"CLTC",n=new Set([t]);x==null||x.tokens.forEach(o=>{const r=o.token.trim().toUpperCase();(x==null?void 0:x.balances.find(a=>a.nft_series===0&&a.asset.trim().toUpperCase()===r&&Y(a.balance,"Balance")>0n))&&n.add(r)}),n.forEach(o=>{const r=document.createElement("option");r.value=o,r.textContent=o,e.append(r)}),Re()}function nr(){if(!x)throw new Error("Wallet balances are still loading.");P=void 0,G=void 0,c("send-form").reset(),c("send-asset").disabled=!1,c("send-amount").disabled=!1,tr(),I("send-screen")}function rr(e){if(!x)throw new Error("Wallet balances are still loading.");P=e,G=void 0,c("send-form").reset();const t=c("send-asset");t.replaceChildren();const n=document.createElement("option");n.value=e.name,n.textContent=be(e),t.append(n),t.disabled=!0;const o=c("send-amount");e.ownership_type===0?(o.value="1.00000000",o.disabled=!0):(o.value="",o.disabled=!1),Re(),I("send-screen")}async function or(){var w;if(!(g!=null&&g.address))throw new Error("No active wallet is available.");const e=(P==null?void 0:P.name)??c("send-asset").value,t=P?be(P):e,n=Q(c("send-recipient").value,"Enter a receiving address."),o=Q(c("send-amount").value,"Enter an amount to send."),r=Q(c("send-fee").value,"Enter a transaction fee."),i=Y(o,"Amount"),a=Y(r,"Transaction fee");if(i===0n)throw new Error("The transfer amount must be greater than zero.");if((P==null?void 0:P.ownership_type)===0&&i!==100000000n)throw new Error("An indivisible NFT must be transferred as one complete asset.");if((P==null?void 0:P.ownership_type)===1&&i>100000000n)throw new Error("A fractional NFT/RWA transfer cannot exceed one complete asset.");const l=cn();if(as)throw new Error(`Insufficient ${e} balance.`);const d=g.networkSymbol,u=((w=x==null?void 0:x.balances.find(R=>R.nft_series===0&&R.asset.trim().toUpperCase()===d))==null?void 0:w.balance)??"0.00000000",m=Y(u,"Base balance");if((e===d?i+a:a)>m)throw new Error(`Insufficient ${d} balance including the fee.`);const f=await $("wallet-prepare-transfer",{receiver:n,asset:e,nftSeries:(P==null?void 0:P.series)??0,valueAtomic:i.toString(),feeAtomic:a.toString()}),h=e===d?`${ne(i+a)} ${d}`:`${ne(i)} ${t} + ${ne(a)} ${d}`;G={transaction:f.transaction,receiverInput:f.receiverInput,asset:e,amount:ne(i),fee:ne(a),total:h},c("review-amount").textContent=G.amount,c("review-asset").textContent=t,c("review-sender").textContent=g.address,c("review-recipient").textContent=f.receiverInput,c("review-resolved-recipient").textContent=String(f.review.receiver??""),c("review-fee").textContent=G.fee,c("review-total").textContent=h,I("send-review-screen")}function ln(e){if(!/^[0-9a-f]+$/i.test(e)||e.length<10)return;const t=e.slice(2,10).match(/../g);if(!t||t.length!==4)return;const n=t.reduce((r,i,a)=>r+Number.parseInt(i,16)*2**(a*8),0),o=new Date(n*1e3);return Number.isNaN(o.getTime())?void 0:o}function ir(e){return e.split("_").map(t=>t&&`${t[0].toUpperCase()}${t.slice(1)}`).join(" ")}function re(e){try{const t=ne(BigInt(String(e??"0"))),[n,o]=t.split("."),r=o.replace(/0+$/,"");return r?`${n}.${r}`:`${n}.0`}catch{return String(e??"")}}function ar(e,t){var o;return t.startsWith("txfee")?!0:((o={1:new Set(["value"]),2:new Set(["value"]),3:new Set(["number"]),6:new Set(["value1","value2","tip1","tip2"]),7:new Set(["loan_amount","collateral_amount","payment_amount","max_late_value"]),8:new Set(["payback_amount","tip"]),10:new Set(["value"]),11:new Set(["number"])}[e])==null?void 0:o.has(t))??!1}function dn(e,t,n){if(typeof n=="boolean")return n?"True":"False";if(ar(e,t))return re(n);if(t==="time"||t==="timestamp"||t==="offer_expiration"){const o=Number(n);if(Number.isFinite(o))return`${new Date(o*1e3).toLocaleString()} (${o})`}return t==="payment_period"?{d:"Daily",w:"Weekly",m:"Monthly"}[String(n).trim().toLowerCase()]??String(n??""):e===3&&t==="hard_limit"?Number(n)===1?"Yes":"No":e===4&&t==="series"?Number(n)===1?"Series":"Single NFT/RWA":e===4&&t==="ownership_type"?Number(n)===1?"Fractional ownership":"Complete ownership":(e===201||e===202)&&t==="vote"?Number(n)===1?"Approve":"Reject":(t==="previous"||t.endsWith("_hash"))&&/^0+$/.test(String(n))?"None":e===5&&(t==="impression_value"||t==="click_value")?(Number(n)/100).toFixed(2):typeof n=="string"?n.trim():String(n??"")}function q(e,t,n,o=!1,r=0){const i=document.createElement("div");i.className=`transaction-field${o?" technical-field":""}`;const a=document.createElement("span");a.textContent=ir(t);const l=document.createElement("strong");l.textContent=o?String(n??""):dn(r,t,n),i.append(a,l),e.append(i)}function ht(e,t){return!e||!t||t=he?`${n} confirmations`:`${n}/${he} confirmations`:`Pending · 0/${he} confirmations`}async function fn(e,t="activity"){_e=e,tn=t;const n=c("close-transaction");n.title=t==="nft"?"Back to NFT/RWA details":"Back to activity",n.setAttribute("aria-label",t==="nft"?"Back to NFT/RWA details":"Back to activity"),I("transaction-screen"),c("transaction-title").textContent="Loading transaction",c("transaction-header-status").textContent="",c("transaction-full-txid").textContent=e.txid,c("transaction-overview").replaceChildren(),c("transaction-fields").replaceChildren(),c("transaction-technical-fields").replaceChildren(),c("transaction-miner-earnings").replaceChildren(),c("miner-earnings-section").hidden=!0;try{const o=await $("wallet-transaction",{txid:e.txid}),r=await Yt((g==null?void 0:g.selectedNetwork)??"testnet"),i=JSON.parse(r.decode_transaction(o.transaction_hex)),l=ht(o.block_height,o.current_height){q(u,f,h,!1,i.txtype)});const m=e.miner_earnings??[];if(m.length>0){const f=c("transaction-miner-earnings");m.forEach((h,w)=>{q(f,`earning_${w+1}_type`,h.type),q(f,`earning_${w+1}_asset`,h.asset),q(f,`earning_${w+1}_nft_series`,h.nft_series),q(f,`earning_${w+1}_amount`,`${re(h.amount_atomic)} ${h.asset.trim()}`)}),c("miner-earnings-section").hidden=!1}const p=c("transaction-technical-fields");i.stored_hash&&q(p,"stored_hash",i.stored_hash,!0),i.signature&&q(p,"signature",i.signature,!0),i.signature1&&q(p,"signature_1",i.signature1,!0),i.signature2&&q(p,"signature_2",i.signature2,!0),q(p,"raw_transaction_bytes",o.transaction_hex,!0)}catch(o){c("transaction-title").textContent="Transaction unavailable";const r=c("transaction-fields");r.replaceChildren(),q(r,"error",F(o))}}function ue(e){const t=String(e??"").trim();return t.length>18?`${t.slice(0,8)}...${t.slice(-7)}`:t}function sr(e,t){const n=e.fields,o=t.trim().toLowerCase(),r=(g==null?void 0:g.networkSymbol)??"CLTC",i=s=>String(n[s]??"").trim(),a=(s,d,u="")=>`${u}${re(n[s])} ${d}`,l=()=>`-${re(n.txfee??0)} ${r}`;switch(e.txtype){case 1:return{title:"Mining reward",subtitle:"From network",amount:a("value",r,"+"),direction:"incoming"};case 2:{const s=i("coin"),d=String(n.sender??"").trim().toLowerCase()===o;return{title:d?`Sent ${s}`:`Received ${s}`,subtitle:d?`To: ${ue(n.receiver)}`:`From: ${ue(n.sender)}`,amount:a("value",s,d?"-":"+"),direction:d?"outgoing":"incoming"}}case 3:{const s=i("ticker");return{title:`Created ${s}`,subtitle:"Token creation",amount:a("number",s,"+"),secondary:l(),direction:"incoming"}}case 4:{const s=String(n.count??"1");return{title:`Created ${i("nft_name")}`,subtitle:Number(n.series??0)===0?"NFT/RWA":"NFT/RWA collection",amount:`+${s} ${Number(s)===1?"item":"items"}`,secondary:l(),direction:"incoming"}}case 6:{const s=String(n.sender1??"").trim().toLowerCase()===o,d=i(s?"ticker1":"ticker2"),u=i(s?"ticker2":"ticker1");return{title:"Completed swap",subtitle:`With: ${ue(n[s?"sender2":"sender1"])}`,amount:a(s?"value1":"value2",d,"-"),secondary:a(s?"value2":"value1",u,"+"),direction:"neutral"}}case 7:{const s=String(n.lender??"").trim().toLowerCase()===o;return{title:s?"Loan funded":"Loan received",subtitle:s?`To: ${ue(n.borrower)}`:`From: ${ue(n.lender)}`,amount:a("loan_amount",i("loan_coin"),s?"-":"+"),direction:s?"outgoing":"incoming"}}case 8:return{title:"Loan payment",subtitle:`Contract: ${ue(n.contract_hash)}`,amount:`-${re(n.payback_amount)}`,direction:"outgoing"};case 10:return{title:`Burned ${i("coin")}`,subtitle:"Removed from supply",amount:a("value",i("coin"),"-"),direction:"outgoing"};case 11:{const s=i("ticker");return{title:`Issued ${s}`,subtitle:"Additional token supply",amount:a("number",s,"+"),secondary:l(),direction:"incoming"}}case 12:return{title:"Created vanity address",subtitle:String(n.vanity_address??"").trim(),amount:l(),direction:"outgoing"};default:return{title:e.transaction_name,subtitle:"Contractless transaction",amount:l(),direction:"outgoing"}}}async function cr(e,t){const n=c("activity-list");if(n.replaceChildren(),c("activity-count").textContent=`${e.length} shown`,e.length===0){const r=document.createElement("div");r.className="activity-empty";const i=document.createElement("strong");i.textContent="No wallet activity found";const a=document.createElement("span");a.textContent="New transactions will appear here after they reach the selected API.",r.append(i,a),n.append(r);return}const o=await Yt((g==null?void 0:g.selectedNetwork)??"testnet");e.forEach(r=>{let i;try{i=JSON.parse(o.decode_transaction(r.transaction_hex))}catch{const E=Number.parseInt(r.transaction_hex.slice(0,2),16);i={txtype:E,transaction_name:On[E]??`Transaction Type ${E}`,fields:{}}}const a=sr(i,(g==null?void 0:g.address)??""),l=ln(r.transaction_hex),d=ht(r.block_height,t){fn(r)}),n.append(u)})}async function mn(){if(!(g!=null&&g.unlocked))return;c("activity-count").textContent="Loading";const e=c("activity-list");e.replaceChildren();const t=document.createElement("div");t.className="activity-empty",t.textContent="Loading recent activity...",e.append(t);try{const n=await $("wallet-activity");await cr(Array.isArray(n.transactions)?n.transactions:[],Number(n.current_height??0))}catch(n){e.replaceChildren();const o=document.createElement("div");o.className="activity-empty activity-error",o.textContent=F(n),e.append(o),c("activity-count").textContent="Unavailable"}}function F(e){return e instanceof Error?e.message:String(e).replace(/^JsValue\((.*)\)$/,"$1")}async function U(e,t=!1){M.textContent="",t&&I("loading");try{await e()}catch(n){throw M.textContent=F(n),n}}function Q(e,t){if(!e.trim())throw new Error(t);return e}function lr(e){let t="";for(let o=0;oURL.revokeObjectURL(r),1e3)}async function gn(e,t){g=e,fe=t,ie=String(await $("export-private-key-image",{password:t,imagePassword:t})),c("wallet-image-preview").src=`data:image/png;base64,${ie}`;const n=c("backup-confirmed");n.disabled=!0,n.checked=!1,c("open-wallet").disabled=!0,I("backup-screen")}document.querySelectorAll(".navigation").forEach(e=>{e.addEventListener("click",()=>{const t=String(e.dataset.screen);if(t==="image-screen"&&en){chrome.tabs.create({url:chrome.runtime.getURL("import-wallet.html"),active:!0});return}I(t)})});c("account-menu-button").addEventListener("click",()=>z(!0));c("close-account-drawer").addEventListener("click",()=>z(!1));c("drawer-backdrop").addEventListener("click",()=>z(!1));function hn(e){z(!1),c("cancel-wallet-add").hidden=!1,I(e)}c("menu-create-wallet").addEventListener("click",()=>{hn("create-screen")});c("menu-import-wallet").addEventListener("click",()=>{z(!1),en?chrome.tabs.create({url:chrome.runtime.getURL("import-wallet.html"),active:!0}):hn("image-screen")});c("cancel-wallet-add").addEventListener("click",()=>{c("cancel-wallet-add").hidden=!0,g&&V(g)});c("menu-settings").addEventListener("click",()=>{z(!1),gt(),g&&(c("settings-testnet-api-url").value=g.testnetApiUrl,c("settings-mainnet-api-url").value=g.mainnetApiUrl,c("settings-lock-timeout").value=String(g.autoLockMinutes)),I("settings-screen")});c("close-settings").addEventListener("click",()=>{gt(),g&&V(g)});c("drawer-lock-wallet").addEventListener("click",()=>{U(async()=>{z(!1),fe="",ie="",V(await $("lock"))})});c("open-receive").addEventListener("click",()=>{U(er)});c("open-send").addEventListener("click",()=>{U(async()=>nr())});c("close-send").addEventListener("click",()=>{G=void 0,P?(xe(P),I("nft-detail-screen")):g&&V(g)});c("send-asset").addEventListener("change",Re);c("send-amount").addEventListener("input",Re);c("send-form").addEventListener("submit",e=>{e.preventDefault(),U(or)});c("send-form").addEventListener("keydown",e=>{!(e instanceof KeyboardEvent)||e.key!=="Enter"||e.target instanceof HTMLInputElement&&(e.preventDefault(),c("send-form").requestSubmit())});c("edit-send").addEventListener("click",()=>{I("send-screen")});c("sign-broadcast-transfer").addEventListener("click",()=>{U(async()=>{if(!G)throw new Error("The reviewed transfer is unavailable.");ve=(await $("wallet-broadcast-transfer",{transaction:G.transaction})).txid,c("send-result-txid").textContent=ve,G=void 0,I("send-success-screen")})});c("copy-send-txid").addEventListener("click",()=>{ve&&navigator.clipboard.writeText(ve).then(()=>{M.textContent="Transaction ID copied."}).catch(e=>{M.textContent=F(e)})});c("finish-send").addEventListener("click",()=>{ve="";const e=!!P;P=void 0,g&&(Be(),e?(Z=void 0,I("nfts-screen"),pt(!0)):V(g))});c("open-activity").addEventListener("click",()=>{I("activity-screen"),mn()});c("open-nfts").addEventListener("click",()=>{K=1,Z=void 0,I("nfts-screen"),pt(!0)});c("close-nfts").addEventListener("click",()=>{ae+=1,g&&V(g)});c("refresh-nfts").addEventListener("click",()=>{pt(!0)});c("close-nft-detail").addEventListener("click",()=>{Z=void 0,I("nfts-screen")});c("transfer-nft").addEventListener("click",()=>{U(async()=>{if(!Z)throw new Error("No NFT or RWA is selected.");rr(Z)})});c("nfts-previous").addEventListener("click",()=>{if(K<=1)return;K-=1;const e=++ae;Ce(),mt(e)});c("nfts-next").addEventListener("click",()=>{const e=Math.max(1,Math.ceil(H.length/we));if(K>=e)return;K+=1;const t=++ae;Ce(),mt(t)});c("close-activity").addEventListener("click",()=>{g&&V(g)});c("close-transaction").addEventListener("click",()=>{tn==="nft"&&Z?(xe(Z),I("nft-detail-screen")):I("activity-screen")});c("copy-transaction-txid").addEventListener("click",()=>{const e=_e==null?void 0:_e.txid;e&&navigator.clipboard.writeText(e).then(()=>{M.textContent="Transaction ID copied."}).catch(t=>{M.textContent=F(t)})});c("refresh-activity").addEventListener("click",()=>{mn()});c("refresh-balances").addEventListener("click",()=>{Be()});document.querySelectorAll("[data-token-filter]").forEach(e=>{e.addEventListener("click",()=>{Te=e.dataset.tokenFilter==="all"?"all":"held",document.querySelectorAll("[data-token-filter]").forEach(t=>{t.classList.toggle("active",t===e)}),st()})});c("close-receive").addEventListener("click",()=>{g&&V(g)});c("copy-receive-address").addEventListener("click",()=>{var t;const e=(t=c("receive-address-value").textContent)==null?void 0:t.trim();if(!e){M.textContent="No active wallet address is available.";return}navigator.clipboard.writeText(e).then(()=>{M.textContent="Wallet address copied."}).catch(n=>{M.textContent=F(n)})});c("save-wallet-settings").addEventListener("click",()=>{U(async()=>{const e=c("settings-testnet-api-url").value.replace(/\/+$/,""),t=c("settings-mainnet-api-url").value.replace(/\/+$/,"");if(!e)throw new Error("A testnet API URL is required.");for(const n of[e,t].filter(Boolean)){const o=new URL(n);if(o.protocol!=="https:"&&o.hostname!=="localhost"&&o.hostname!=="127.0.0.1")throw new Error("Contractless API URLs must use HTTPS.");const r=`${o.origin}/*`;if(!await chrome.permissions.contains({origins:[r]})&&!await chrome.permissions.request({origins:[r]}))throw new Error("Permission to contact this API endpoint was denied.")}g=await $("save-settings",{testnetApiUrl:e,mainnetApiUrl:t,autoLockMinutes:c("settings-lock-timeout").value}),M.textContent="Settings saved."})});document.querySelectorAll("[data-select-network]").forEach(e=>{e.addEventListener("click",()=>{const t=e.dataset.selectNetwork;!t||t===(g==null?void 0:g.selectedNetwork)||U(async()=>{z(!1),V(await $("switch-network",{network:t}))})})});document.querySelectorAll("[data-backup-action]").forEach(e=>{e.addEventListener("click",()=>{dt=e.dataset.backupAction,Ee(!0)})});c("close-backup-key").addEventListener("click",()=>Ee(!1));c("backup-key-backdrop").addEventListener("click",()=>Ee(!1));c("confirm-backup-key").addEventListener("click",()=>{const e=dt,t=c("backup-key-input").value;if(e){if(!t){M.textContent="Enter the active wallet encryption key.";return}U(async()=>{var r;if(e==="image"){const i=String(await $("export-private-key-image",{password:t,imagePassword:t})),a=((r=g==null?void 0:g.address)==null?void 0:r.split(".")[0])??"contractless";pn(i,`${a}.wallet.png`),Ee(!1),M.textContent="Wallet image downloaded.";return}const n=await $("reveal-private-key",{password:t});if(Ee(!1),e==="private"){c("revealed-private-key").value=n.privateKey,c("private-key-result").hidden=!1,c("private-key-result").scrollIntoView({block:"nearest"});return}const o=crypto.randomUUID();await chrome.storage.session.set({[`print-backup:${o}`]:{label:n.label,address:n.address,privateKey:n.privateKey,encryptionKey:t}}),await chrome.windows.create({url:chrome.runtime.getURL(`print.html?id=${encodeURIComponent(o)}`),type:"popup",width:820,height:760})})}});c("clear-private-key").addEventListener("click",gt);c("copy-private-key").addEventListener("click",()=>{const e=c("revealed-private-key").value;e&&navigator.clipboard.writeText(e).then(()=>{M.textContent="Private key copied."}).catch(t=>{M.textContent=F(t)})});document.querySelectorAll(".reveal").forEach(e=>{e.addEventListener("click",()=>{const t=c(String(e.dataset.input)),n=t.type==="text";t.type=n?"password":"text",e.textContent=n?"Show":"Hide"})});c("continue-create").addEventListener("click",()=>{try{Le=Q(c("new-password").value,"Enter an encryption key."),c("verify-password").value="",I("verify-screen")}catch(e){M.textContent=F(e)}});c("create-wallet").addEventListener("click",()=>{if(c("verify-password").value!==Le){M.textContent="The encryption keys do not match.";return}U(async()=>{const t=Le,n=await $("create-wallet",{password:t});Le="",c("new-password").value="",c("verify-password").value="",await gn(n,t)},!0).catch(()=>I("verify-screen",!1))});const ct=c("wallet-image");ct.addEventListener("change",()=>{var t;const e=(t=ct.files)==null?void 0:t[0];ge="",c("image-file-name").textContent=(e==null?void 0:e.name)??"Choose wallet image",e&&e.arrayBuffer().then(n=>{ge=lr(new Uint8Array(n))}).catch(n=>{M.textContent=F(n)})});c("import-image-form").addEventListener("submit",e=>{e.preventDefault();const t=c("image-password").value;try{Q(t,"Enter the wallet image encryption key."),Q(ge,"Choose a wallet image.")}catch(n){M.textContent=F(n);return}U(async()=>{const n=await $("import-wallet-image",{imageBase64:ge,imagePassword:t,password:t});fe=t,ge="",ct.value="",c("image-password").value="",V(n)},!0).catch(()=>I("image-screen",!1))});c("import-private").addEventListener("click",()=>{const e=c("private-key").value.trim(),t=c("private-password").value;try{Q(e,"Paste the private key."),Q(t,"Enter a new encryption key.")}catch(n){M.textContent=F(n);return}U(async()=>{const n=await $("import-private-key",{privateKey:e,password:t});c("private-key").value="",c("private-password").value="",await gn(n,t)},!0).catch(()=>I("private-screen",!1))});c("save-image").addEventListener("click",()=>{U(async()=>{var n;if(!ie)throw new Error("The wallet image is not ready.");const e=((n=g==null?void 0:g.address)==null?void 0:n.split(".")[0])??"contractless";pn(ie,`${e}.wallet.png`);const t=c("backup-confirmed");t.disabled=!1,t.checked=!1,c("open-wallet").disabled=!0})});c("backup-confirmed").addEventListener("change",e=>{c("open-wallet").disabled=!e.currentTarget.checked});c("open-wallet").addEventListener("click",()=>{fe="",ie="",c("wallet-image-preview").removeAttribute("src"),g&&V(g)});c("unlock-form").addEventListener("submit",e=>{e.preventDefault();const t=c("unlock-password").value;try{Q(t,"Enter your encryption key.")}catch(n){M.textContent=F(n);return}U(async()=>{const n=await $("unlock",{password:t});fe=t,c("unlock-password").value="",V(n)},!0).catch(()=>I("locked-screen",!1))});c("approve-provider-approval").addEventListener("click",()=>{oe&&(ye("approve"),U(async()=>{const e=await $("resolve-provider-approval",{id:oe,approved:!0});oe="",await nn(e.remaining??0,!0)}).catch(()=>ye(null)))});c("reject-provider-approval").addEventListener("click",()=>{oe&&(ye("reject"),U(async()=>{const e=await $("resolve-provider-approval",{id:oe,approved:!1});oe="",await nn(e.remaining??0,!1)}).catch(()=>ye(null)))});$("status").then(e=>V(e)).catch(e=>{I("create-screen"),M.textContent=F(e)}); +`);const S=E(N,A,T),k=e.getSymbolSize(N),_=new o(k);return p(_,N),h(_),w(_,N),C(_,A,0),N>=7&&x(_,N),B(_,S),isNaN(v)&&(v=a.getBestMask(_,C.bind(null,_,A))),a.applyMask(v,_),C(_,A,v),{modules:_,version:N,errorCorrectionLevel:A,maskPattern:v,segments:T}}return De.create=function(N,A){if(typeof N>"u"||N==="")throw new Error("No input text");let v=t.M,T,b;return typeof A<"u"&&(v=t.from(A.errorCorrectionLevel,t.M),T=d.from(A.version),b=a.from(A.maskPattern),A.toSJISFunc&&e.setToSJISFunction(A.toSJISFunc)),U(N,T,v,b)},De}var rt={},ot={},Ot;function en(){return Ot||(Ot=1,(function(e){function t(n){if(typeof n=="number"&&(n=n.toString()),typeof n!="string")throw new Error("Color should be defined as hex string");let o=n.slice().replace("#","").split("");if(o.length<3||o.length===5||o.length>8)throw new Error("Invalid hex color: "+n);(o.length===3||o.length===4)&&(o=Array.prototype.concat.apply([],o.map(function(i){return[i,i]}))),o.length===6&&o.push("F","F");const r=parseInt(o.join(""),16);return{r:r>>24&255,g:r>>16&255,b:r>>8&255,a:r&255,hex:"#"+o.slice(0,6).join("")}}e.getOptions=function(o){o||(o={}),o.color||(o.color={});const r=typeof o.margin>"u"||o.margin===null||o.margin<0?4:o.margin,i=o.width&&o.width>=21?o.width:void 0,a=o.scale||4;return{width:i,scale:i?4:a,margin:r,color:{dark:t(o.color.dark||"#000000ff"),light:t(o.color.light||"#ffffffff")},type:o.type,rendererOpts:o.rendererOpts||{}}},e.getScale=function(o,r){return r.width&&r.width>=o+r.margin*2?r.width/(o+r.margin*2):r.scale},e.getImageWidth=function(o,r){const i=e.getScale(o,r);return Math.floor((o+r.margin*2)*i)},e.qrToImageData=function(o,r,i){const a=r.modules.size,l=r.modules.data,s=e.getScale(a,i),d=Math.floor((a+i.margin*2)*s),u=i.margin*s,f=[i.color.light,i.color.dark];for(let g=0;g=u&&p>=u&&g"u"&&(!a||!a.getContext)&&(s=a,a=void 0),a||(d=o()),s=t.getOptions(s);const u=t.getImageWidth(i.modules.size,s),f=d.getContext("2d"),g=f.createImageData(u,u);return t.qrToImageData(g.data,i,s),n(f,d,u),f.putImageData(g,0,0),d},e.renderToDataURL=function(i,a,l){let s=l;typeof s>"u"&&(!a||!a.getContext)&&(s=a,a=void 0),s||(s={});const d=e.render(i,a,s),u=s.type||"image/png",f=s.rendererOpts||{};return d.toDataURL(u,f.quality)}})(rt)),rt}var it={},Wt;function Kn(){if(Wt)return it;Wt=1;const e=en();function t(r,i){const a=r.a/255,l=i+'="'+r.hex+'"';return a<1?l+" "+i+'-opacity="'+a.toFixed(2).slice(1)+'"':l}function n(r,i,a){let l=r+i;return typeof a<"u"&&(l+=" "+a),l}function o(r,i,a){let l="",s=0,d=!1,u=0;for(let f=0;f0&&g>0&&r[f-1]||(l+=d?n("M",g+a,.5+p+a):n("m",s,0),s=0,d=!1),g+1':"",p="',h='viewBox="0 0 '+f+" "+f+'"',x=''+g+p+` +`;return typeof l=="function"&&l(null,x),x},it}var Ht;function jn(){if(Ht)return de;Ht=1;const e=kn(),t=Fn(),n=Vn(),o=Kn();function r(i,a,l,s,d){const u=[].slice.call(arguments,1),f=u.length,g=typeof u[f-1]=="function";if(!g&&!e())throw new Error("Callback required as last argument");if(g){if(f<2)throw new Error("Too few arguments provided");f===2?(d=l,l=a,a=s=void 0):f===3&&(a.getContext&&typeof d>"u"?(d=s,s=void 0):(d=s,s=l,l=a,a=void 0))}else{if(f<1)throw new Error("Too few arguments provided");return f===1?(l=a,a=s=void 0):f===2&&!a.getContext&&(s=l,l=a,a=void 0),new Promise(function(p,h){try{const w=t.create(l,s);p(i(w,a,s))}catch(w){h(w)}})}try{const p=t.create(l,s);d(null,i(p,a,s))}catch(p){d(p)}}return de.create=t.create,de.toCanvas=r.bind(null,n.render),de.toDataURL=r.bind(null,n.renderToDataURL),de.toString=r.bind(null,function(i,a,l){return o.render(i,l)}),de}var zn=jn();const On=bn(zn),c=e=>document.getElementById(e),Jn=Array.from(document.querySelectorAll(".screen")),M=c("notice"),tn=navigator.userAgent.includes("Firefox");let Te="",fe="",ge="",ie="",m,ut,_e="held",K=1,ae=0;const we=8;let R,H=[],Z,P,Be,nn="activity",G,ve="",oe="";const he=20,Wn=15e3;let at=!1;const Hn={1:"Mining Reward",2:"Transfer",3:"Token Creation",4:"NFT/RWA Creation",5:"Marketing",6:"Swap",7:"Loan",8:"Loan Payment",9:"Collateral Claim",10:"Asset Burn",11:"Token Issuance",12:"Vanity Address",100:"Storage Key",101:"Data Storage Bool",102:"Data Storage U8",103:"Data Storage U16",104:"Data Storage U32",105:"Data Storage U64",106:"Data Storage U128",107:"Data Storage String",108:"Data Storage I8",109:"Data Storage I16",110:"Data Storage I32",111:"Data Storage I64",112:"Data Storage I128",113:"Delete Stored Data",200:"Proposal",201:"Proposal Vote",202:"Activation Vote"};async function $(e,t={}){const n=await chrome.runtime.sendMessage({type:e,...t});if(!(n!=null&&n.ok))throw new Error((n==null?void 0:n.error)??"Wallet request failed.");return n.result}function I(e,t=!0){Jn.forEach(n=>{n.hidden=n.id!==e}),t&&(M.textContent="")}function V(e){m=e;const t=e.networkName,n=e.networkSymbol;document.querySelectorAll("[data-network-name]").forEach(o=>{o.textContent=t}),document.querySelectorAll("[data-network-symbol]").forEach(o=>{o.textContent=n}),c("base-asset-name").textContent=`Contractless ${t}`,c("wallet-address").textContent=e.address??"",c("wallet-address-short").textContent=e.address?`${e.address.slice(0,6)}...${e.address.slice(-6)}`:"Account",c("settings-testnet-api-url").value=e.testnetApiUrl,c("settings-mainnet-api-url").value=e.mainnetApiUrl,document.querySelectorAll("[data-select-network]").forEach(o=>{const r=o.dataset.selectNetwork===e.selectedNetwork;o.classList.toggle("active",r),o.setAttribute("aria-pressed",String(r))}),c("settings-lock-timeout").value=String(e.autoLockMinutes),nr(e),e.exists?e.unlocked?st().then(o=>{o||(I("dashboard-screen"),be())}):I("locked-screen"):I("create-screen")}function Yn(e,t){return e==="contractless_connect"?"Connect application":e==="contractless_signMessage"?"Sign text message":e==="contractless_sendTransaction"||e==="contractless_signDualTransaction"?`Sign ${String(t.transaction_type??"transaction")}`:"Review request"}function j(e,t,n){const o=document.createElement("dt");o.textContent=t.replaceAll("_"," ");const r=document.createElement("dd");r.textContent=typeof n=="object"?JSON.stringify(n,null,2):String(n),e.append(o,r)}function te(e,t,n,o){const r=re(e[t]),i=String(e[n]??"").trim().toUpperCase(),a=Number(e[o]??0);return`${r} ${i}${a>0?` #${a}`:""}`}function Yt(e,t,n){const o=n===1?2:1,r=(m==null?void 0:m.networkSymbol)??"CLTC";j(e,"Your miner tip",te(t,`tip${n}`,`ticker${n}`,`nft_series${n}`)),j(e,"Your transaction fee",`${re(t[`txfee${n}`])} ${r}`),j(e,"Other party miner tip",te(t,`tip${o}`,`ticker${o}`,`nft_series${o}`)),j(e,"Other party transaction fee",`${re(t[`txfee${o}`])} ${r}`)}function Gn(e,t){var a;const n=((a=m==null?void 0:m.address)==null?void 0:a.trim().toLowerCase())??"",o=String(t.sender1??"").trim().toLowerCase(),r=String(t.sender2??"").trim().toLowerCase(),i=n===o?1:n===r?2:0;if(i===1){j(e,"Sending",te(t,"value1","ticker1","nft_series1")),j(e,"Receiving",te(t,"value2","ticker2","nft_series2")),Yt(e,t,1);return}if(i===2){j(e,"Sending",te(t,"value2","ticker2","nft_series2")),j(e,"Receiving",te(t,"value1","ticker1","nft_series1")),Yt(e,t,2);return}j(e,"First party sending",te(t,"value1","ticker1","nft_series1")),j(e,"Second party sending",te(t,"value2","ticker2","nft_series2"))}function ye(e){const t=c("approve-provider-approval"),n=c("reject-provider-approval"),o=e!==null;t.disabled=o,n.disabled=o,t.classList.toggle("is-processing",e==="approve"),n.classList.toggle("is-processing",e==="reject"),t.textContent=e==="approve"?"Processing...":"Approve",n.textContent=e==="reject"?"Rejecting...":"Reject"}async function st(){const e=await $("pending-provider-approval");if(!(e!=null&&e.request))return!1;const t=e.request;ye(null),oe=t.id;const n=(e.total??0)>1?` · Request ${e.position??1} of ${e.total}`:"";c("provider-approval-origin").textContent=`${t.origin}${n}`;const o=c("provider-approval-risk");o.className=`risk-label risk-${t.risk}`,o.textContent=t.risk==="safe"?"Safe":t.risk==="low"?"Low risk":"High risk";const r=t.display??{},i=t.method==="contractless_sendTransaction"||t.method==="contractless_signDualTransaction";c("provider-approval-title").textContent=Yn(t.method,r),c("provider-approval-intro").textContent=i?"Review every transaction field before signing.":"Review this request before approving it.";const a=c("provider-approval-details");return a.replaceChildren(),Object.entries(r).forEach(([l,s])=>{if(l==="transaction_fields"&&s&&typeof s=="object"){const d=s,u=Number(d.txtype??0),f=new Set(["ticker1","nft_series1","value1","ticker2","nft_series2","value2","tip1","tip2","txfee1","txfee2"]);u===6&&Gn(a,d),Object.entries(d).forEach(([g,p])=>{u===6&&f.has(g)||j(a,g==="txtype"?"transaction_type_id":g,fn(u,g,p))});return}j(a,l,s)}),I("provider-approval-screen"),!0}async function rn(e,t){if(!(e>0&&await st())){if(t){const n=Date.now()+1500;for(;Date.now()setTimeout(o,75))}}window.close()}}function Qn(e){return e.replace(/[.0]/g,"").length>0}function ct(){const e=c("token-list");if(e.replaceChildren(),!R){const s=document.createElement("div");s.className="empty-assets";const d=document.createElement("strong");d.textContent="Loading token balances...";const u=document.createElement("span");u.textContent="Balances are retrieved from the selected Contractless API.",s.append(d,u),e.append(s);return}const t=(m==null?void 0:m.networkSymbol)??"CLTC",n=new Set(R.tokens.map(s=>s.token.trim().toUpperCase())),o=new Set(R.nfts.map(s=>`${s.name.trim().toUpperCase()}|${Number(s.series||0)}`)),r=R.balances.filter(s=>{const d=s.asset.trim().toUpperCase(),u=`${d}|${Number(s.nft_series||0)}`;return s.nft_series===0&&d!=="CLTC"&&d!=="CLC"&&n.has(d)&&!o.has(u)}),i=new Map(r.map(s=>[s.asset.trim().toUpperCase(),s])),a=_e==="all"?R.tokens.map(s=>s.token):r.filter(s=>Qn(s.balance)).map(s=>s.asset),l=[...new Set(a.map(s=>s.trim().toUpperCase()))].filter(s=>s!==t&&!o.has(`${s}|0`)).sort((s,d)=>s.localeCompare(d));if(l.length===0){const s=document.createElement("div");s.className="empty-assets";const d=document.createElement("strong");d.textContent=_e==="held"?"No token balances found":"No tokens found";const u=document.createElement("span");u.textContent=_e==="held"?"Switch to All tokens to view the complete network token list.":R.tokenCatalogError?`Token catalog unavailable: ${R.tokenCatalogError}`:"The selected API did not return any fungible tokens.",s.append(d,u),e.append(s);return}l.forEach(s=>{const d=i.get(s),u=document.createElement("div");u.className="asset-row";const f=document.createElement("div");f.className="asset-symbol token-symbol",f.textContent=s.slice(0,3);const g=document.createElement("div");g.className="asset-name";const p=document.createElement("strong");p.textContent=s;const h=document.createElement("span");h.textContent="Contractless token",g.append(p,h);const w=document.createElement("div");w.className="asset-value";const x=document.createElement("strong");x.textContent=(d==null?void 0:d.balance)??"0.00000000";const C=document.createElement("span");C.textContent=s,w.append(x,C),u.append(f,g,w),e.append(u)})}async function be(e={}){if(!(m!=null&&m.unlocked)||at)return;const t=m.address,n=m.selectedNetwork,o=m.apiUrl,r=R!==void 0,i=e.showLoading??!r,a=e.reportErrors??!0;at=!0,i&&(R=void 0,c("base-balance").textContent="--",c("base-asset-balance").textContent="--",ct());try{if(!m.apiUrl)throw new Error(`No ${m.networkName} API is configured.`);const l=await $("wallet-balances");if(!(m!=null&&m.unlocked)||m.address!==t||m.selectedNetwork!==n||m.apiUrl!==o)return;R={balances:Array.isArray(l.balances)?l.balances:[],tokens:Array.isArray(l.tokens)?l.tokens:[],nfts:Array.isArray(l.nfts)?l.nfts:[],tokenCatalogError:l.tokenCatalogError,nftCatalogError:l.nftCatalogError};const s=m.networkSymbol,d=R.balances.find(f=>f.nft_series===0&&f.asset.toUpperCase()===s),u=(d==null?void 0:d.balance)??"0.00000000";c("base-balance").textContent=u,c("base-asset-balance").textContent=u,ct()}catch(l){if(!r){const s=c("token-list");s.replaceChildren();const d=document.createElement("div");d.className="empty-assets balance-error";const u=document.createElement("strong");u.textContent="Unable to load balances";const f=document.createElement("span");f.textContent=F(l),d.append(u,f),s.append(d)}a&&(M.textContent=F(l))}finally{at=!1}}function on(){document.hidden||c("dashboard-screen").hidden||!(m!=null&&m.unlocked)||be({showLoading:!1,reportErrors:!1})}function Se(e,t){return`${e.trim().toUpperCase()}|${t}`}function Zn(e){try{return Y(e,"Balance")>0n}catch{return!1}}function an(e){if(e.ownership_type!==1)return"Complete ownership";try{const t=Y(e.balance,"Balance"),n=Y(e.supply,"Supply");if(n<=0n)return"0% ownership";const o=t*100000000n/n,r=o/1000000n,i=(o%1000000n).toString().padStart(6,"0").replace(/0+$/,"");return`${r}${i?`.${i}`:""}% ownership`}catch{return"Fractional ownership"}}function ft(e){var t;return(t=e.details)!=null&&t.metadata&&typeof e.details.metadata=="object"?e.details.metadata:{}}function mt(e){const t=ft(e).name;return typeof t=="string"&&t.trim()?t.trim():e.series>0?`${e.name} #${e.series}`:e.name}function sn(e){const n=ft(e).contractless;return n&&typeof n=="object"&&String(n.metadata_type??"").toLowerCase()==="rwa"?"RWA":"NFT"}function ke(e){return e.series>0?`${e.name}_${e.series}`:e.name}function Xn(e,t=7,n=7){return e.length>t+n+3?`${e.slice(0,t)}...${e.slice(-n)}`:e}function er(e,t){var r;const n=document.createElement("div");if(n.className=t,(r=e.details)!=null&&r.image_data_url){const i=document.createElement("img");return i.src=e.details.image_data_url,i.alt=mt(e),n.append(i),n}const o=document.createElement("span");return o.textContent=e.loading?"...":e.name.slice(0,2).toUpperCase(),n.append(o),n}function cn(){const e=(K-1)*we;return H.slice(e,e+we)}function Ce(){const e=c("nfts-list");e.replaceChildren();const t=Math.max(1,Math.ceil(H.length/we));if(K=Math.min(Math.max(1,K),t),c("nfts-count").textContent=H.length===1?"1 owned asset":`${H.length} owned assets`,c("nfts-page").textContent=String(K),c("nfts-pages").textContent=String(t),c("nfts-pagination").hidden=t<=1,c("nfts-previous").disabled=K<=1,c("nfts-next").disabled=K>=t,!H.length){const n=document.createElement("div");n.className="nfts-empty";const o=document.createElement("strong");o.textContent="No NFTs or RWAs found";const r=document.createElement("span");r.textContent=R!=null&&R.nftCatalogError?`NFT catalog unavailable: ${R.nftCatalogError}`:"Assets owned by this wallet will appear here.",n.append(o,r),e.append(n);return}cn().forEach(n=>{const o=document.createElement("button");o.type="button",o.className="nft-card",o.append(er(n,"nft-card-media"));const r=document.createElement("div");r.className="nft-card-identity";const i=document.createElement("span");i.textContent=sn(n);const a=document.createElement("strong");a.textContent=mt(n);const l=document.createElement("small");l.textContent=ke(n);const s=document.createElement("b");if(s.textContent=an(n),r.append(i,a,l,s),n.error){const d=document.createElement("em");d.textContent="Media unavailable",r.append(d)}o.append(r),o.addEventListener("click",()=>tr(n)),e.append(o)})}function Le(e,t,n){const o=document.createElement("div"),r=document.createElement("dt");r.textContent=t;const i=document.createElement("dd");i.textContent=n||"--",o.append(r,i),e.append(o)}function Re(e){Z=e;const t=e.details,n=ft(e),o=sn(e),r=mt(e);c("nft-detail-title").textContent=r,c("nft-detail-kind").textContent=`${o} details`,c("nft-detail-badge").textContent=o,c("nft-detail-name").textContent=r,c("nft-detail-ownership").textContent=an(e);const i=c("nft-detail-image");i.src=(t==null?void 0:t.image_data_url)??"",i.alt=r,i.hidden=!(t!=null&&t.image_data_url);const a=n.description??n.summary;c("nft-detail-description").textContent=typeof a=="string"&&a.trim()?a.trim():t?"No description was included in the NFT metadata.":"Loading NFT metadata and provenance...";const l=c("nft-detail-attributes");l.replaceChildren(),(Array.isArray(n.attributes)?n.attributes.slice(0,12):[]).forEach(f=>{if(!f||typeof f!="object")return;const g=f,p=document.createElement("div"),h=document.createElement("span");h.textContent=String(g.trait_type??g.type??"Attribute");const w=document.createElement("strong");w.textContent=String(g.value??""),p.append(h,w),l.append(p)}),l.hidden=l.childElementCount===0;const d=c("nft-detail-fields");d.replaceChildren(),Le(d,"Asset",ke(e)),Le(d,"Creator",(t==null?void 0:t.creator)??"--"),Le(d,"IPFS CID",(t==null?void 0:t.item_ipfs)??"--"),Le(d,"Origin transaction",(t==null?void 0:t.genesis_txid)??e.origin_txid);const u=c("nft-detail-history");if(u.replaceChildren(),t)if(t.history.length)t.history.slice().reverse().forEach(f=>{const g=document.createElement("button");g.type="button",g.className="nft-history-row",g.title=`View full transaction ${f.txid}`;const p=document.createElement("strong");p.textContent=f.action;const h=document.createElement("span");h.textContent=`Block ${Number(f.block).toLocaleString()}`;const w=document.createElement("small");w.textContent=Xn(f.txid),g.append(p,h,w),g.addEventListener("click",()=>{pn({txid:f.txid,block_height:Number(f.block),transaction_hex:""},"nft")}),u.append(g)});else{const f=document.createElement("p");f.textContent="No provenance records were returned.",u.append(f)}else{const f=document.createElement("p");f.textContent="Loading provenance...",u.append(f)}}function tr(e){Re(e),I("nft-detail-screen")}async function pt(e){const t=cn().filter(r=>!r.details&&!r.loading);let n=0;const o=async()=>{for(;n[Se(r.name,r.series),r]));H=R.nfts.map(r=>{const i=R==null?void 0:R.balances.find(l=>Se(l.asset,Number(l.nft_series||0))===Se(r.name,Number(r.series||0)));if(!i||!Zn(i.balance))return null;const a=n.get(Se(r.name,r.series));return{name:r.name.trim(),series:Number(r.series||0),origin_txid:r.origin_txid,ownership_type:Number(r.ownership_type||0),supply:r.supply,balance:i.balance,details:a==null?void 0:a.details,error:a==null?void 0:a.error}}).filter(r=>r!==null).sort((r,i)=>r.name.localeCompare(i.name)||r.series-i.series);const o=Math.max(1,Math.ceil(H.length/we));K=Math.min(K,o),Ce(),await pt(t)}function nr(e){const t=c("known-addresses");t.replaceChildren(),e.wallets.forEach(n=>{const o=document.createElement("div");o.className=`known-address${n.active?" active-address":""}`;const r=document.createElement("button");r.type="button",r.className="address-select",r.dataset.walletId=n.id;const i=document.createElement("span");i.className="address-avatar";const a=document.createElement("img");a.src=chrome.runtime.getURL("contractless-logo.png"),a.alt="",i.append(a);const l=document.createElement("span");l.className="address-details";const s=document.createElement("strong");s.textContent=n.label;const d=document.createElement("small");d.textContent=n.address,l.append(s,d);const u=document.createElement("span");u.className="selected-mark",u.textContent=n.active?"✓":"",r.append(i,l,u),r.addEventListener("click",()=>{if(n.active){z(!1);return}D(async()=>{z(!1),fe="",ie="",V(await $("switch-wallet",{walletId:n.id}))})});const f=document.createElement("button");f.type="button",f.className="rename-address",f.title="Rename wallet",f.setAttribute("aria-label",`Rename ${n.label}`),f.textContent="✎",f.addEventListener("click",()=>{const g=window.prompt("Wallet label",n.label);g===null||g.trim()===n.label||D(async()=>{const p=await $("rename-wallet",{walletId:n.id,label:g});V(p),z(!0)})}),o.append(r,f),t.append(o)})}function z(e){const t=c("account-drawer"),n=c("drawer-backdrop"),o=c("account-menu-button");t.classList.toggle("open",e),t.setAttribute("aria-hidden",String(!e)),o.setAttribute("aria-expanded",String(e)),n.hidden=!e}function ht(){c("revealed-private-key").value="",c("private-key-result").hidden=!0}function Ee(e){if(c("backup-key-modal").hidden=!e,c("backup-key-backdrop").hidden=!e,e){const t=c("backup-key-input");t.value="",t.focus()}else c("backup-key-input").value="",ut=void 0}async function rr(){const e=await $("wallet-receive-address"),t=String(e.receiveAddress??"");if(!t)throw new Error("No active wallet address is available.");c("receive-address-label").textContent=e.vanity?"Vanity address":"Wallet address",c("receive-address-value").textContent=t;const n=c("receive-qr");await On.toCanvas(n,t,{width:220,margin:1,errorCorrectionLevel:"M",color:{dark:"#071016",light:"#ffffff"}}),I("receive-screen")}function Y(e,t){const n=e.trim();if(!/^(?:0|[1-9]\d*)(?:\.\d{1,8})?$/.test(n))throw new Error(`${t} must be a positive number with no more than 8 decimal places.`);const[o,r=""]=n.split(".");return BigInt(o)*100000000n+BigInt(r.padEnd(8,"0"))}function ne(e){const t=e/100000000n,n=(e%100000000n).toString().padStart(8,"0");return`${t}.${n}`}function ln(){if(P)return P.balance;const e=c("send-asset").value,t=R==null?void 0:R.balances.find(n=>n.nft_series===0&&n.asset.trim().toUpperCase()===e);return(t==null?void 0:t.balance)??"0.00000000"}function dn(){const e=c("send-asset").value,t=(m==null?void 0:m.networkSymbol)??"CLTC";if(e!==t)return 100000000n;const n=c("send-amount").value.trim();if(!n)return 0n;try{return(Y(n,"Amount")+99n)/100n}catch{return 0n}}function xe(){const e=(P==null?void 0:P.name)??c("send-asset").value,t=(m==null?void 0:m.networkSymbol)??"CLTC",n=P?ke(P):e;c("send-amount-symbol").textContent=n,c("send-available").textContent=`Available: ${ln()} ${n}`;const o=dn();c("send-fee").value=ne(o),c("send-fee-note").textContent=!P&&e===t?"Minimum fee: 1% of the transfer amount.":`Minimum fee: 1 ${t} for asset transfers.`}function or(){const e=c("send-asset");e.replaceChildren();const t=(m==null?void 0:m.networkSymbol)??"CLTC",n=new Set([t]);R==null||R.tokens.forEach(o=>{const r=o.token.trim().toUpperCase();(R==null?void 0:R.balances.find(a=>a.nft_series===0&&a.asset.trim().toUpperCase()===r&&Y(a.balance,"Balance")>0n))&&n.add(r)}),n.forEach(o=>{const r=document.createElement("option");r.value=o,r.textContent=o,e.append(r)}),xe()}function ir(){if(!R)throw new Error("Wallet balances are still loading.");P=void 0,G=void 0,c("send-form").reset(),c("send-asset").disabled=!1,c("send-amount").disabled=!1,or(),I("send-screen")}function ar(e){if(!R)throw new Error("Wallet balances are still loading.");P=e,G=void 0,c("send-form").reset();const t=c("send-asset");t.replaceChildren();const n=document.createElement("option");n.value=e.name,n.textContent=ke(e),t.append(n),t.disabled=!0;const o=c("send-amount");e.ownership_type===0?(o.value="1.00000000",o.disabled=!0):(o.value="",o.disabled=!1),xe(),I("send-screen")}async function sr(){var w;if(!(m!=null&&m.address))throw new Error("No active wallet is available.");const e=(P==null?void 0:P.name)??c("send-asset").value,t=P?ke(P):e,n=Q(c("send-recipient").value,"Enter a receiving address."),o=Q(c("send-amount").value,"Enter an amount to send."),r=Q(c("send-fee").value,"Enter a transaction fee."),i=Y(o,"Amount"),a=Y(r,"Transaction fee");if(i===0n)throw new Error("The transfer amount must be greater than zero.");if((P==null?void 0:P.ownership_type)===0&&i!==100000000n)throw new Error("An indivisible NFT must be transferred as one complete asset.");if((P==null?void 0:P.ownership_type)===1&&i>100000000n)throw new Error("A fractional NFT/RWA transfer cannot exceed one complete asset.");const l=dn();if(as)throw new Error(`Insufficient ${e} balance.`);const d=m.networkSymbol,u=((w=R==null?void 0:R.balances.find(x=>x.nft_series===0&&x.asset.trim().toUpperCase()===d))==null?void 0:w.balance)??"0.00000000",f=Y(u,"Base balance");if((e===d?i+a:a)>f)throw new Error(`Insufficient ${d} balance including the fee.`);const p=await $("wallet-prepare-transfer",{receiver:n,asset:e,nftSeries:(P==null?void 0:P.series)??0,valueAtomic:i.toString(),feeAtomic:a.toString()}),h=e===d?`${ne(i+a)} ${d}`:`${ne(i)} ${t} + ${ne(a)} ${d}`;G={transaction:p.transaction,receiverInput:p.receiverInput,asset:e,amount:ne(i),fee:ne(a),total:h},c("review-amount").textContent=G.amount,c("review-asset").textContent=t,c("review-sender").textContent=m.address,c("review-recipient").textContent=p.receiverInput,c("review-resolved-recipient").textContent=String(p.review.receiver??""),c("review-fee").textContent=G.fee,c("review-total").textContent=h,I("send-review-screen")}function un(e){if(!/^[0-9a-f]+$/i.test(e)||e.length<10)return;const t=e.slice(2,10).match(/../g);if(!t||t.length!==4)return;const n=t.reduce((r,i,a)=>r+Number.parseInt(i,16)*2**(a*8),0),o=new Date(n*1e3);return Number.isNaN(o.getTime())?void 0:o}function cr(e){return e.split("_").map(t=>t&&`${t[0].toUpperCase()}${t.slice(1)}`).join(" ")}function re(e){try{const t=ne(BigInt(String(e??"0"))),[n,o]=t.split("."),r=o.replace(/0+$/,"");return r?`${n}.${r}`:`${n}.0`}catch{return String(e??"")}}function lr(e,t){var o;return t.startsWith("txfee")?!0:((o={1:new Set(["value"]),2:new Set(["value"]),3:new Set(["number"]),6:new Set(["value1","value2","tip1","tip2"]),7:new Set(["loan_amount","collateral_amount","payment_amount","max_late_value"]),8:new Set(["payback_amount","tip"]),10:new Set(["value"]),11:new Set(["number"])}[e])==null?void 0:o.has(t))??!1}function fn(e,t,n){if(typeof n=="boolean")return n?"True":"False";if(lr(e,t))return re(n);if(t==="time"||t==="timestamp"||t==="offer_expiration"){const o=Number(n);if(Number.isFinite(o))return`${new Date(o*1e3).toLocaleString()} (${o})`}return t==="payment_period"?{d:"Daily",w:"Weekly",m:"Monthly"}[String(n).trim().toLowerCase()]??String(n??""):e===3&&t==="hard_limit"?Number(n)===1?"Yes":"No":e===4&&t==="series"?Number(n)===1?"Series":"Single NFT/RWA":e===4&&t==="ownership_type"?Number(n)===1?"Fractional ownership":"Complete ownership":(e===201||e===202)&&t==="vote"?Number(n)===1?"Approve":"Reject":(t==="previous"||t.endsWith("_hash"))&&/^0+$/.test(String(n))?"None":e===5&&(t==="impression_value"||t==="click_value")?(Number(n)/100).toFixed(2):typeof n=="string"?n.trim():String(n??"")}function q(e,t,n,o=!1,r=0){const i=document.createElement("div");i.className=`transaction-field${o?" technical-field":""}`;const a=document.createElement("span");a.textContent=cr(t);const l=document.createElement("strong");l.textContent=o?String(n??""):fn(r,t,n),i.append(a,l),e.append(i)}function wt(e,t){return!e||!t||t=he?`${n} confirmations`:`${n}/${he} confirmations`:`Pending · 0/${he} confirmations`}async function pn(e,t="activity"){Be=e,nn=t;const n=c("close-transaction");n.title=t==="nft"?"Back to NFT/RWA details":"Back to activity",n.setAttribute("aria-label",t==="nft"?"Back to NFT/RWA details":"Back to activity"),I("transaction-screen"),c("transaction-title").textContent="Loading transaction",c("transaction-header-status").textContent="",c("transaction-full-txid").textContent=e.txid,c("transaction-overview").replaceChildren(),c("transaction-fields").replaceChildren(),c("transaction-technical-fields").replaceChildren(),c("transaction-miner-earnings").replaceChildren(),c("miner-earnings-section").hidden=!0;try{const o=await $("wallet-transaction",{txid:e.txid}),r=await Gt((m==null?void 0:m.selectedNetwork)??"testnet"),i=JSON.parse(r.decode_transaction(o.transaction_hex)),l=wt(o.block_height,o.current_height){q(u,p,h,!1,i.txtype)});const f=e.miner_earnings??[];if(f.length>0){const p=c("transaction-miner-earnings");f.forEach((h,w)=>{q(p,`earning_${w+1}_type`,h.type),q(p,`earning_${w+1}_asset`,h.asset),q(p,`earning_${w+1}_nft_series`,h.nft_series),q(p,`earning_${w+1}_amount`,`${re(h.amount_atomic)} ${h.asset.trim()}`)}),c("miner-earnings-section").hidden=!1}const g=c("transaction-technical-fields");i.stored_hash&&q(g,"stored_hash",i.stored_hash,!0),i.signature&&q(g,"signature",i.signature,!0),i.signature1&&q(g,"signature_1",i.signature1,!0),i.signature2&&q(g,"signature_2",i.signature2,!0),q(g,"raw_transaction_bytes",o.transaction_hex,!0)}catch(o){c("transaction-title").textContent="Transaction unavailable";const r=c("transaction-fields");r.replaceChildren(),q(r,"error",F(o))}}function ue(e){const t=String(e??"").trim();return t.length>18?`${t.slice(0,8)}...${t.slice(-7)}`:t}function dr(e,t){const n=e.fields,o=t.trim().toLowerCase(),r=(m==null?void 0:m.networkSymbol)??"CLTC",i=s=>String(n[s]??"").trim(),a=(s,d,u="")=>`${u}${re(n[s])} ${d}`,l=()=>`-${re(n.txfee??0)} ${r}`;switch(e.txtype){case 1:return{title:"Mining reward",subtitle:"From network",amount:a("value",r,"+"),direction:"incoming"};case 2:{const s=i("coin"),d=String(n.sender??"").trim().toLowerCase()===o;return{title:d?`Sent ${s}`:`Received ${s}`,subtitle:d?`To: ${ue(n.receiver)}`:`From: ${ue(n.sender)}`,amount:a("value",s,d?"-":"+"),direction:d?"outgoing":"incoming"}}case 3:{const s=i("ticker");return{title:`Created ${s}`,subtitle:"Token creation",amount:a("number",s,"+"),secondary:l(),direction:"incoming"}}case 4:{const s=String(n.count??"1");return{title:`Created ${i("nft_name")}`,subtitle:Number(n.series??0)===0?"NFT/RWA":"NFT/RWA collection",amount:`+${s} ${Number(s)===1?"item":"items"}`,secondary:l(),direction:"incoming"}}case 6:{const s=String(n.sender1??"").trim().toLowerCase()===o,d=i(s?"ticker1":"ticker2"),u=i(s?"ticker2":"ticker1");return{title:"Completed swap",subtitle:`With: ${ue(n[s?"sender2":"sender1"])}`,amount:a(s?"value1":"value2",d,"-"),secondary:a(s?"value2":"value1",u,"+"),direction:"neutral"}}case 7:{const s=String(n.lender??"").trim().toLowerCase()===o;return{title:s?"Loan funded":"Loan received",subtitle:s?`To: ${ue(n.borrower)}`:`From: ${ue(n.lender)}`,amount:a("loan_amount",i("loan_coin"),s?"-":"+"),direction:s?"outgoing":"incoming"}}case 8:return{title:"Loan payment",subtitle:`Contract: ${ue(n.contract_hash)}`,amount:`-${re(n.payback_amount)}`,direction:"outgoing"};case 10:return{title:`Burned ${i("coin")}`,subtitle:"Removed from supply",amount:a("value",i("coin"),"-"),direction:"outgoing"};case 11:{const s=i("ticker");return{title:`Issued ${s}`,subtitle:"Additional token supply",amount:a("number",s,"+"),secondary:l(),direction:"incoming"}}case 12:return{title:"Created vanity address",subtitle:String(n.vanity_address??"").trim(),amount:l(),direction:"outgoing"};default:return{title:e.transaction_name,subtitle:"Contractless transaction",amount:l(),direction:"outgoing"}}}async function ur(e,t){const n=c("activity-list");if(n.replaceChildren(),c("activity-count").textContent=`${e.length} shown`,e.length===0){const r=document.createElement("div");r.className="activity-empty";const i=document.createElement("strong");i.textContent="No wallet activity found";const a=document.createElement("span");a.textContent="New transactions will appear here after they reach the selected API.",r.append(i,a),n.append(r);return}const o=await Gt((m==null?void 0:m.selectedNetwork)??"testnet");e.forEach(r=>{let i;try{i=JSON.parse(o.decode_transaction(r.transaction_hex))}catch{const E=Number.parseInt(r.transaction_hex.slice(0,2),16);i={txtype:E,transaction_name:Hn[E]??`Transaction Type ${E}`,fields:{}}}const a=dr(i,(m==null?void 0:m.address)??""),l=un(r.transaction_hex),d=wt(r.block_height,t){pn(r)}),n.append(u)})}async function gn(){if(!(m!=null&&m.unlocked))return;c("activity-count").textContent="Loading";const e=c("activity-list");e.replaceChildren();const t=document.createElement("div");t.className="activity-empty",t.textContent="Loading recent activity...",e.append(t);try{const n=await $("wallet-activity");await ur(Array.isArray(n.transactions)?n.transactions:[],Number(n.current_height??0))}catch(n){e.replaceChildren();const o=document.createElement("div");o.className="activity-empty activity-error",o.textContent=F(n),e.append(o),c("activity-count").textContent="Unavailable"}}function F(e){return e instanceof Error?e.message:String(e).replace(/^JsValue\((.*)\)$/,"$1")}async function D(e,t=!1){M.textContent="",t&&I("loading");try{await e()}catch(n){throw M.textContent=F(n),n}}function Q(e,t){if(!e.trim())throw new Error(t);return e}function fr(e){let t="";for(let o=0;oURL.revokeObjectURL(r),1e3)}async function wn(e,t){m=e,fe=t,ie=String(await $("export-private-key-image",{password:t,imagePassword:t})),c("wallet-image-preview").src=`data:image/png;base64,${ie}`;const n=c("backup-confirmed");n.disabled=!0,n.checked=!1,c("open-wallet").disabled=!0,I("backup-screen")}document.querySelectorAll(".navigation").forEach(e=>{e.addEventListener("click",()=>{const t=String(e.dataset.screen);if(t==="image-screen"&&tn){chrome.tabs.create({url:chrome.runtime.getURL("import-wallet.html"),active:!0});return}I(t)})});c("account-menu-button").addEventListener("click",()=>z(!0));c("close-account-drawer").addEventListener("click",()=>z(!1));c("drawer-backdrop").addEventListener("click",()=>z(!1));function vn(e){z(!1),c("cancel-wallet-add").hidden=!1,I(e)}c("menu-create-wallet").addEventListener("click",()=>{vn("create-screen")});c("menu-import-wallet").addEventListener("click",()=>{z(!1),tn?chrome.tabs.create({url:chrome.runtime.getURL("import-wallet.html"),active:!0}):vn("image-screen")});c("cancel-wallet-add").addEventListener("click",()=>{c("cancel-wallet-add").hidden=!0,m&&V(m)});c("menu-settings").addEventListener("click",()=>{z(!1),ht(),m&&(c("settings-testnet-api-url").value=m.testnetApiUrl,c("settings-mainnet-api-url").value=m.mainnetApiUrl,c("settings-lock-timeout").value=String(m.autoLockMinutes)),I("settings-screen")});c("close-settings").addEventListener("click",()=>{ht(),m&&V(m)});c("drawer-lock-wallet").addEventListener("click",()=>{D(async()=>{z(!1),fe="",ie="",V(await $("lock"))})});c("open-receive").addEventListener("click",()=>{D(rr)});c("open-send").addEventListener("click",()=>{D(async()=>ir())});c("close-send").addEventListener("click",()=>{G=void 0,P?(Re(P),I("nft-detail-screen")):m&&V(m)});c("send-asset").addEventListener("change",xe);c("send-amount").addEventListener("input",xe);c("send-form").addEventListener("submit",e=>{e.preventDefault(),D(sr)});c("send-form").addEventListener("keydown",e=>{!(e instanceof KeyboardEvent)||e.key!=="Enter"||e.target instanceof HTMLInputElement&&(e.preventDefault(),c("send-form").requestSubmit())});c("edit-send").addEventListener("click",()=>{I("send-screen")});c("sign-broadcast-transfer").addEventListener("click",()=>{D(async()=>{if(!G)throw new Error("The reviewed transfer is unavailable.");ve=(await $("wallet-broadcast-transfer",{transaction:G.transaction})).txid,c("send-result-txid").textContent=ve,G=void 0,I("send-success-screen")})});c("copy-send-txid").addEventListener("click",()=>{ve&&navigator.clipboard.writeText(ve).then(()=>{M.textContent="Transaction ID copied."}).catch(e=>{M.textContent=F(e)})});c("finish-send").addEventListener("click",()=>{ve="";const e=!!P;P=void 0,m&&(be(),e?(Z=void 0,I("nfts-screen"),gt(!0)):V(m))});c("open-activity").addEventListener("click",()=>{I("activity-screen"),gn()});c("open-nfts").addEventListener("click",()=>{K=1,Z=void 0,I("nfts-screen"),gt(!0)});c("close-nfts").addEventListener("click",()=>{ae+=1,m&&V(m)});c("refresh-nfts").addEventListener("click",()=>{gt(!0)});c("close-nft-detail").addEventListener("click",()=>{Z=void 0,I("nfts-screen")});c("transfer-nft").addEventListener("click",()=>{D(async()=>{if(!Z)throw new Error("No NFT or RWA is selected.");ar(Z)})});c("nfts-previous").addEventListener("click",()=>{if(K<=1)return;K-=1;const e=++ae;Ce(),pt(e)});c("nfts-next").addEventListener("click",()=>{const e=Math.max(1,Math.ceil(H.length/we));if(K>=e)return;K+=1;const t=++ae;Ce(),pt(t)});c("close-activity").addEventListener("click",()=>{m&&V(m)});c("close-transaction").addEventListener("click",()=>{nn==="nft"&&Z?(Re(Z),I("nft-detail-screen")):I("activity-screen")});c("copy-transaction-txid").addEventListener("click",()=>{const e=Be==null?void 0:Be.txid;e&&navigator.clipboard.writeText(e).then(()=>{M.textContent="Transaction ID copied."}).catch(t=>{M.textContent=F(t)})});c("refresh-activity").addEventListener("click",()=>{gn()});c("refresh-balances").addEventListener("click",()=>{be()});document.querySelectorAll("[data-token-filter]").forEach(e=>{e.addEventListener("click",()=>{_e=e.dataset.tokenFilter==="all"?"all":"held",document.querySelectorAll("[data-token-filter]").forEach(t=>{t.classList.toggle("active",t===e)}),ct()})});c("close-receive").addEventListener("click",()=>{m&&V(m)});c("copy-receive-address").addEventListener("click",()=>{var t;const e=(t=c("receive-address-value").textContent)==null?void 0:t.trim();if(!e){M.textContent="No active wallet address is available.";return}navigator.clipboard.writeText(e).then(()=>{M.textContent="Wallet address copied."}).catch(n=>{M.textContent=F(n)})});c("save-wallet-settings").addEventListener("click",()=>{D(async()=>{const e=c("settings-testnet-api-url").value.replace(/\/+$/,""),t=c("settings-mainnet-api-url").value.replace(/\/+$/,"");if(!e)throw new Error("A testnet API URL is required.");for(const n of[e,t].filter(Boolean)){const o=new URL(n);if(o.protocol!=="https:"&&o.hostname!=="localhost"&&o.hostname!=="127.0.0.1")throw new Error("Contractless API URLs must use HTTPS.");const r=`${o.origin}/*`;if(!await chrome.permissions.contains({origins:[r]})&&!await chrome.permissions.request({origins:[r]}))throw new Error("Permission to contact this API endpoint was denied.")}m=await $("save-settings",{testnetApiUrl:e,mainnetApiUrl:t,autoLockMinutes:c("settings-lock-timeout").value}),M.textContent="Settings saved."})});document.querySelectorAll("[data-select-network]").forEach(e=>{e.addEventListener("click",()=>{const t=e.dataset.selectNetwork;!t||t===(m==null?void 0:m.selectedNetwork)||D(async()=>{z(!1),V(await $("switch-network",{network:t}))})})});document.querySelectorAll("[data-backup-action]").forEach(e=>{e.addEventListener("click",()=>{ut=e.dataset.backupAction,Ee(!0)})});c("close-backup-key").addEventListener("click",()=>Ee(!1));c("backup-key-backdrop").addEventListener("click",()=>Ee(!1));c("confirm-backup-key").addEventListener("click",()=>{const e=ut,t=c("backup-key-input").value;if(e){if(!t){M.textContent="Enter the active wallet encryption key.";return}D(async()=>{var r;if(e==="image"){const i=String(await $("export-private-key-image",{password:t,imagePassword:t})),a=((r=m==null?void 0:m.address)==null?void 0:r.split(".")[0])??"contractless";hn(i,`${a}.wallet.png`),Ee(!1),M.textContent="Wallet image downloaded.";return}const n=await $("reveal-private-key",{password:t});if(Ee(!1),e==="private"){c("revealed-private-key").value=n.privateKey,c("private-key-result").hidden=!1,c("private-key-result").scrollIntoView({block:"nearest"});return}const o=crypto.randomUUID();await chrome.storage.session.set({[`print-backup:${o}`]:{label:n.label,address:n.address,privateKey:n.privateKey,encryptionKey:t}}),await chrome.windows.create({url:chrome.runtime.getURL(`print.html?id=${encodeURIComponent(o)}`),type:"popup",width:820,height:760})})}});c("clear-private-key").addEventListener("click",ht);c("copy-private-key").addEventListener("click",()=>{const e=c("revealed-private-key").value;e&&navigator.clipboard.writeText(e).then(()=>{M.textContent="Private key copied."}).catch(t=>{M.textContent=F(t)})});document.querySelectorAll(".reveal").forEach(e=>{e.addEventListener("click",()=>{const t=c(String(e.dataset.input)),n=t.type==="text";t.type=n?"password":"text",e.textContent=n?"Show":"Hide"})});c("continue-create").addEventListener("click",()=>{try{Te=Q(c("new-password").value,"Enter an encryption key."),c("verify-password").value="",I("verify-screen")}catch(e){M.textContent=F(e)}});c("create-wallet").addEventListener("click",()=>{if(c("verify-password").value!==Te){M.textContent="The encryption keys do not match.";return}D(async()=>{const t=Te,n=await $("create-wallet",{password:t});Te="",c("new-password").value="",c("verify-password").value="",await wn(n,t)},!0).catch(()=>I("verify-screen",!1))});const lt=c("wallet-image");lt.addEventListener("change",()=>{var t;const e=(t=lt.files)==null?void 0:t[0];ge="",c("image-file-name").textContent=(e==null?void 0:e.name)??"Choose wallet image",e&&e.arrayBuffer().then(n=>{ge=fr(new Uint8Array(n))}).catch(n=>{M.textContent=F(n)})});c("import-image-form").addEventListener("submit",e=>{e.preventDefault();const t=c("image-password").value;try{Q(t,"Enter the wallet image encryption key."),Q(ge,"Choose a wallet image.")}catch(n){M.textContent=F(n);return}D(async()=>{const n=await $("import-wallet-image",{imageBase64:ge,imagePassword:t,password:t});fe=t,ge="",lt.value="",c("image-password").value="",V(n)},!0).catch(()=>I("image-screen",!1))});c("import-private").addEventListener("click",()=>{const e=c("private-key").value.trim(),t=c("private-password").value;try{Q(e,"Paste the private key."),Q(t,"Enter a new encryption key.")}catch(n){M.textContent=F(n);return}D(async()=>{const n=await $("import-private-key",{privateKey:e,password:t});c("private-key").value="",c("private-password").value="",await wn(n,t)},!0).catch(()=>I("private-screen",!1))});c("save-image").addEventListener("click",()=>{D(async()=>{var n;if(!ie)throw new Error("The wallet image is not ready.");const e=((n=m==null?void 0:m.address)==null?void 0:n.split(".")[0])??"contractless";hn(ie,`${e}.wallet.png`);const t=c("backup-confirmed");t.disabled=!1,t.checked=!1,c("open-wallet").disabled=!0})});c("backup-confirmed").addEventListener("change",e=>{c("open-wallet").disabled=!e.currentTarget.checked});c("open-wallet").addEventListener("click",()=>{fe="",ie="",c("wallet-image-preview").removeAttribute("src"),m&&V(m)});c("unlock-form").addEventListener("submit",e=>{e.preventDefault();const t=c("unlock-password").value;try{Q(t,"Enter your encryption key.")}catch(n){M.textContent=F(n);return}D(async()=>{const n=await $("unlock",{password:t});fe=t,c("unlock-password").value="",V(n)},!0).catch(()=>I("locked-screen",!1))});c("approve-provider-approval").addEventListener("click",()=>{oe&&(ye("approve"),D(async()=>{const e=await $("resolve-provider-approval",{id:oe,approved:!0});oe="",await rn(e.remaining??0,!0)}).catch(()=>ye(null)))});c("reject-provider-approval").addEventListener("click",()=>{oe&&(ye("reject"),D(async()=>{const e=await $("resolve-provider-approval",{id:oe,approved:!1});oe="",await rn(e.remaining??0,!1)}).catch(()=>ye(null)))});window.setInterval(on,Wn);document.addEventListener("visibilitychange",on);$("status").then(e=>V(e)).catch(e=>{I("create-screen"),M.textContent=F(e)}); diff --git a/extension/dist/chunks/core-CvwXoH-U.js b/extension/dist/chunks/core-CvwXoH-U.js deleted file mode 100644 index 559b415..0000000 --- a/extension/dist/chunks/core-CvwXoH-U.js +++ /dev/null @@ -1 +0,0 @@ -function I(t,e,r,_,o){let l,c;try{const w=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),d=a,y=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),m=a,b=s(r,n.__wbindgen_malloc,n.__wbindgen_realloc),p=a,q=s(_,n.__wbindgen_malloc,n.__wbindgen_realloc),v=a,F=s(o,n.__wbindgen_malloc,n.__wbindgen_realloc),U=a,k=n.complete_dual_transaction_request(w,d,y,m,b,p,q,v,F,U);var i=k[0],f=k[1];if(k[3])throw i=0,f=0,u(k[2]);return l=i,c=f,g(i,f)}finally{n.__wbindgen_free(l,c,1)}}function M(t,e){let r,_;try{const c=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),i=a,f=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),w=a,d=n.create_handshake_proof(c,i,f,w);var o=d[0],l=d[1];if(d[3])throw o=0,l=0,u(d[2]);return r=o,_=l,g(o,l)}finally{n.__wbindgen_free(r,_,1)}}function B(t,e){let r,_;try{const c=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),i=a,f=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),w=a,d=n.create_wallet_registration(c,i,f,w);var o=d[0],l=d[1];if(d[3])throw o=0,l=0,u(d[2]);return r=o,_=l,g(o,l)}finally{n.__wbindgen_free(r,_,1)}}function C(t,e,r){let _,o;try{const i=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),f=a,w=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),d=a,y=s(r,n.__wbindgen_malloc,n.__wbindgen_realloc),m=a,b=n.create_wallet_registration_from_keys(i,f,w,d,y,m);var l=b[0],c=b[1];if(b[3])throw l=0,c=0,u(b[2]);return _=l,o=c,g(l,c)}finally{n.__wbindgen_free(_,o,1)}}function D(t){let e,r;try{const l=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),c=a,i=n.decode_transaction(l,c);var _=i[0],o=i[1];if(i[3])throw _=0,o=0,u(i[2]);return e=_,r=o,g(_,o)}finally{n.__wbindgen_free(e,r,1)}}function j(t,e,r){let _,o;try{const i=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),f=a,w=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),d=a,y=s(r,n.__wbindgen_malloc,n.__wbindgen_realloc),m=a,b=n.export_legacy_wallet(i,f,w,d,y,m);var l=b[0],c=b[1];if(b[3])throw l=0,c=0,u(b[2]);return _=l,o=c,g(l,c)}finally{n.__wbindgen_free(_,o,1)}}function z(t){let e,r;try{const l=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),c=a,i=n.generate_browser_wallet(l,c);var _=i[0],o=i[1];if(i[3])throw _=0,o=0,u(i[2]);return e=_,r=o,g(_,o)}finally{n.__wbindgen_free(e,r,1)}}function N(t,e,r){let _,o;try{const i=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),f=a,w=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),d=a,y=s(r,n.__wbindgen_malloc,n.__wbindgen_realloc),m=a,b=n.import_legacy_wallet(i,f,w,d,y,m);var l=b[0],c=b[1];if(b[3])throw l=0,c=0,u(b[2]);return _=l,o=c,g(l,c)}finally{n.__wbindgen_free(_,o,1)}}function V(t,e){let r,_;try{const c=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),i=a,f=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),w=a,d=n.import_private_key(c,i,f,w);var o=d[0],l=d[1];if(d[3])throw o=0,l=0,u(d[2]);return r=o,_=l,g(o,l)}finally{n.__wbindgen_free(r,_,1)}}function G(t,e,r){let _,o;try{const i=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),f=a,w=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),d=a,y=s(r,n.__wbindgen_malloc,n.__wbindgen_realloc),m=a,b=n.import_private_key_image(i,f,w,d,y,m);var l=b[0],c=b[1];if(b[3])throw l=0,c=0,u(b[2]);return _=l,o=c,g(l,c)}finally{n.__wbindgen_free(_,o,1)}}function H(t){let e,r;try{const l=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),c=a,i=n.inspect_transaction_request(l,c);var _=i[0],o=i[1];if(i[3])throw _=0,o=0,u(i[2]);return e=_,r=o,g(_,o)}finally{n.__wbindgen_free(e,r,1)}}function P(t,e,r){let _,o;try{const i=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),f=a,w=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),d=a,y=s(r,n.__wbindgen_malloc,n.__wbindgen_realloc),m=a,b=n.sign_message_request(i,f,w,d,y,m);var l=b[0],c=b[1];if(b[3])throw l=0,c=0,u(b[2]);return _=l,o=c,g(l,c)}finally{n.__wbindgen_free(_,o,1)}}function X(t,e,r,_){let o,l;try{const f=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),w=a,d=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),y=a,m=s(r,n.__wbindgen_malloc,n.__wbindgen_realloc),b=a,p=n.sign_transaction_request(f,w,d,y,m,b,_);var c=p[0],i=p[1];if(p[3])throw c=0,i=0,u(p[2]);return o=c,l=i,g(c,i)}finally{n.__wbindgen_free(o,l,1)}}function Y(){let t,e;try{const o=n.transaction_type_registry();var r=o[0],_=o[1];if(o[3])throw r=0,_=0,u(o[2]);return t=r,e=_,g(r,_)}finally{n.__wbindgen_free(t,e,1)}}function J(t,e){let r,_;try{const c=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),i=a,f=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),w=a,d=n.unlock_browser_wallet(c,i,f,w);var o=d[0],l=d[1];if(d[3])throw o=0,l=0,u(d[2]);return r=o,_=l,g(o,l)}finally{n.__wbindgen_free(r,_,1)}}function K(t,e,r,_){let o,l;try{const f=s(t,n.__wbindgen_malloc,n.__wbindgen_realloc),w=a,d=s(e,n.__wbindgen_malloc,n.__wbindgen_realloc),y=a,m=s(r,n.__wbindgen_malloc,n.__wbindgen_realloc),b=a,p=s(_,n.__wbindgen_malloc,n.__wbindgen_realloc),q=a,v=n.verify_message_proof(f,w,d,y,m,b,p,q);var c=v[0],i=v[1];if(v[3])throw c=0,i=0,u(v[2]);return o=c,l=i,g(c,i)}finally{n.__wbindgen_free(o,l,1)}}function Q(){return{__proto__:null,"./contractless_browser_core_bg.js":{__proto__:null,__wbg___wbindgen_is_function_1ff95bcc5517c252:function(e){return typeof e=="function"},__wbg___wbindgen_is_object_a27215656b807791:function(e){const r=e;return typeof r=="object"&&r!==null},__wbg___wbindgen_is_string_ea5e6cc2e4141dfe:function(e){return typeof e=="string"},__wbg___wbindgen_is_undefined_c05833b95a3cf397:function(e){return e===void 0},__wbg___wbindgen_throw_344f42d3211c4765:function(e,r){throw new Error(g(e,r))},__wbg_call_a6e5c5dce5018821:function(){return R(function(e,r,_){return e.call(r,_)},arguments)},__wbg_crypto_38df2bab126b63dc:function(e){return e.crypto},__wbg_getRandomValues_c44a50d8cfdaebeb:function(){return R(function(e,r){e.getRandomValues(r)},arguments)},__wbg_length_1f0964f4a5e2c6d8:function(e){return e.length},__wbg_msCrypto_bd5a034af96bcba6:function(e){return e.msCrypto},__wbg_new_with_length_e6785c33c8e4cce8:function(e){return new Uint8Array(e>>>0)},__wbg_node_84ea875411254db1:function(e){return e.node},__wbg_process_44c7a14e11e9f69e:function(e){return e.process},__wbg_prototypesetcall_4770620bbe4688a0:function(e,r,_){Uint8Array.prototype.set.call(S(e,r),_)},__wbg_randomFillSync_6c25eac9869eb53c:function(){return R(function(e,r){e.randomFillSync(r)},arguments)},__wbg_require_b4edbdcf3e2a1ef0:function(){return R(function(){return module.require},arguments)},__wbg_static_accessor_GLOBAL_4ef717fb391d88b7:function(){const e=typeof global>"u"?null:global;return W(e)?0:h(e)},__wbg_static_accessor_GLOBAL_THIS_8d1badc68b5a74f4:function(){const e=typeof globalThis>"u"?null:globalThis;return W(e)?0:h(e)},__wbg_static_accessor_SELF_146583524fe1469b:function(){const e=typeof self>"u"?null:self;return W(e)?0:h(e)},__wbg_static_accessor_WINDOW_f2829a2234d7819e:function(){const e=typeof window>"u"?null:window;return W(e)?0:h(e)},__wbg_subarray_3ed232c8a6baee09:function(e,r,_){return e.subarray(r>>>0,_>>>0)},__wbg_versions_276b2795b1c6a219:function(e){return e.versions},__wbindgen_cast_0000000000000001:function(e,r){return S(e,r)},__wbindgen_cast_0000000000000002:function(e,r){return g(e,r)},__wbindgen_init_externref_table:function(){const e=n.__wbindgen_externrefs,r=e.grow(4);e.set(0,void 0),e.set(r+0,void 0),e.set(r+1,null),e.set(r+2,!0),e.set(r+3,!1)}}}}function h(t){const e=n.__externref_table_alloc();return n.__wbindgen_externrefs.set(e,t),e}function S(t,e){return t=t>>>0,A().subarray(t/1,t/1+e)}function g(t,e){return $(t>>>0,e)}let x=null;function A(){return(x===null||x.byteLength===0)&&(x=new Uint8Array(n.memory.buffer)),x}function R(t,e){try{return t.apply(this,e)}catch(r){const _=h(r);n.__wbindgen_exn_store(_)}}function W(t){return t==null}function s(t,e,r){if(r===void 0){const i=T.encode(t),f=e(i.length,1)>>>0;return A().subarray(f,f+i.length).set(i),a=i.length,f}let _=t.length,o=e(_,1)>>>0;const l=A();let c=0;for(;c<_;c++){const i=t.charCodeAt(c);if(i>127)break;l[o+c]=i}if(c!==_){c!==0&&(t=t.slice(c)),o=r(o,_,_=c+t.length*3,1)>>>0;const i=A().subarray(o+c,o+_),f=T.encodeInto(t,i);c+=f.written,o=r(o,_,c,1)>>>0}return a=c,o}function u(t){const e=n.__wbindgen_externrefs.get(t);return n.__externref_table_dealloc(t),e}let E=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0});E.decode();const Z=2146435072;let O=0;function $(t,e){return O+=e,O>=Z&&(E=new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}),E.decode(),O=e),E.decode(A().subarray(t,t+e))}const T=new TextEncoder;"encodeInto"in T||(T.encodeInto=function(t,e){const r=T.encode(t);return e.set(r),{read:t.length,written:r.length}});let a=0,n;function ee(t,e){return n=t.exports,x=null,n.__wbindgen_start(),n}async function ne(t,e){if(typeof Response=="function"&&t instanceof Response){if(typeof WebAssembly.instantiateStreaming=="function")try{return await WebAssembly.instantiateStreaming(t,e)}catch(o){if(t.ok&&r(t.type)&&t.headers.get("Content-Type")!=="application/wasm")console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",o);else throw o}const _=await t.arrayBuffer();return await WebAssembly.instantiate(_,e)}else{const _=await WebAssembly.instantiate(t,e);return _ instanceof WebAssembly.Instance?{instance:_,module:t}:_}function r(_){switch(_){case"basic":case"cors":case"default":return!0}return!1}}async function te(t){if(n!==void 0)return n;t!==void 0&&(Object.getPrototypeOf(t)===Object.prototype?{module_or_path:t}=t:console.warn("using deprecated parameters for the initialization function; pass a single object instead")),t===void 0&&(t=new URL("/assets/contractless_browser_core_bg-C_vtp2Os.wasm",import.meta.url));const e=Q();(typeof t=="string"||typeof Request=="function"&&t instanceof Request||typeof URL=="function"&&t instanceof URL)&&(t=fetch(t));const{instance:r,module:_}=await ne(await t,e);return ee(r)}let L;async function re(){return L??(L=te()),await L,{complete_dual_transaction_request:I,create_handshake_proof:M,create_wallet_registration:B,create_wallet_registration_from_keys:C,decode_transaction:D,export_legacy_wallet:j,generate_browser_wallet:z,import_legacy_wallet:N,import_private_key:V,import_private_key_image:G,inspect_transaction_request:H,sign_message_request:P,sign_transaction_request:X,transaction_type_registry:Y,unlock_browser_wallet:J,verify_message_proof:K}}export{re as c}; diff --git a/extension/dist/chunks/modulepreload-polyfill-B5Qt9EMX.js b/extension/dist/chunks/modulepreload-polyfill-B5Qt9EMX.js deleted file mode 100644 index 3e0a78a..0000000 --- a/extension/dist/chunks/modulepreload-polyfill-B5Qt9EMX.js +++ /dev/null @@ -1 +0,0 @@ -(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))i(e);new MutationObserver(e=>{for(const r of e)if(r.type==="childList")for(const o of r.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&i(o)}).observe(document,{childList:!0,subtree:!0});function s(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),e.crossOrigin==="use-credentials"?r.credentials="include":e.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function i(e){if(e.ep)return;e.ep=!0;const r=s(e);fetch(e.href,r)}})(); diff --git a/extension/dist/content.js b/extension/dist/content.js deleted file mode 100644 index 0ce4e56..0000000 --- a/extension/dist/content.js +++ /dev/null @@ -1 +0,0 @@ -const o=document.createElement("script");o.src=chrome.runtime.getURL("provider.js");o.onload=()=>o.remove();(document.head||document.documentElement).appendChild(o);window.addEventListener("message",e=>{var t;e.source!==window||((t=e.data)==null?void 0:t.source)!=="contractless-page"||chrome.runtime.sendMessage({type:"provider-request",method:e.data.method,params:e.data.params},a=>{window.postMessage({source:"contractless-wallet",id:e.data.id,response:a},window.location.origin)})}); diff --git a/extension/dist/contractless-logo.png b/extension/dist/contractless-logo.png deleted file mode 100644 index 729e4d7..0000000 Binary files a/extension/dist/contractless-logo.png and /dev/null differ diff --git a/extension/dist/firefox/manifest.json b/extension/dist/firefox/manifest.json index 389d071..d2357e1 100644 --- a/extension/dist/firefox/manifest.json +++ b/extension/dist/firefox/manifest.json @@ -18,7 +18,7 @@ "content_security_policy": { "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'" }, - "permissions": ["storage", "alarms", "activeTab", "clipboardWrite"], + "permissions": ["storage", "alarms", "clipboardWrite"], "host_permissions": ["https://api.contractless.dev/*"], "optional_host_permissions": ["https://*/"], "action": { diff --git a/extension/dist/manifest.json b/extension/dist/manifest.json deleted file mode 100644 index c8137d2..0000000 --- a/extension/dist/manifest.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "manifest_version": 3, - "name": "Contractless Wallet", - "version": "0.1.1", - "description": "A local-signing Web3 wallet for Contractless.", - "content_security_policy": { - "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'" - }, - "permissions": ["storage", "alarms", "activeTab", "clipboardWrite"], - "host_permissions": ["https://api.contractless.dev/*"], - "optional_host_permissions": ["https://*/"], - "action": { - "default_popup": "popup.html", - "default_title": "Contractless Wallet", - "default_icon": { - "16": "contractless-logo.png", - "32": "contractless-logo.png", - "48": "contractless-logo.png", - "128": "contractless-logo.png" - } - }, - "icons": { - "16": "contractless-logo.png", - "32": "contractless-logo.png", - "48": "contractless-logo.png", - "128": "contractless-logo.png" - }, - "background": { - "service_worker": "background.js", - "type": "module" - }, - "content_scripts": [ - { - "matches": ["https://*/*", "http://localhost/*", "http://127.0.0.1/*"], - "js": ["content.js"], - "run_at": "document_start" - } - ], - "web_accessible_resources": [ - { - "resources": ["provider.js"], - "matches": ["https://*/*", "http://localhost/*", "http://127.0.0.1/*"] - } - ] -} diff --git a/extension/dist/popup.html b/extension/dist/popup.html deleted file mode 100644 index 77a3b93..0000000 --- a/extension/dist/popup.html +++ /dev/null @@ -1,635 +0,0 @@ - - - - - - Contractless Wallet - - - - - - -
-
-
- Contractless -
-
-

Opening wallet

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - diff --git a/extension/dist/popup.js b/extension/dist/popup.js deleted file mode 100644 index 6f113ab..0000000 --- a/extension/dist/popup.js +++ /dev/null @@ -1,8 +0,0 @@ -import"./chunks/modulepreload-polyfill-B5Qt9EMX.js";import{c as Yt}from"./chunks/core-CvwXoH-U.js";function yn(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var de={},De,Ct;function Cn(){return Ct||(Ct=1,De=function(){return typeof Promise=="function"&&Promise.prototype&&Promise.prototype.then}),De}var Ue={},ee={},Et;function se(){if(Et)return ee;Et=1;let e;const t=[0,26,44,70,100,134,172,196,242,292,346,404,466,532,581,655,733,815,901,991,1085,1156,1258,1364,1474,1588,1706,1828,1921,2051,2185,2323,2465,2611,2761,2876,3034,3196,3362,3532,3706];return ee.getSymbolSize=function(o){if(!o)throw new Error('"version" cannot be null or undefined');if(o<1||o>40)throw new Error('"version" should be in range from 1 to 40');return o*4+17},ee.getSymbolTotalCodewords=function(o){return t[o]},ee.getBCHDigit=function(n){let o=0;for(;n!==0;)o++,n>>>=1;return o},ee.setToSJISFunction=function(o){if(typeof o!="function")throw new Error('"toSJISFunc" is not a valid function.');e=o},ee.isKanjiModeEnabled=function(){return typeof e<"u"},ee.toSJIS=function(o){return e(o)},ee}var Fe={},bt;function lt(){return bt||(bt=1,(function(e){e.L={bit:1},e.M={bit:0},e.Q={bit:3},e.H={bit:2};function t(n){if(typeof n!="string")throw new Error("Param is not a string");switch(n.toLowerCase()){case"l":case"low":return e.L;case"m":case"medium":return e.M;case"q":case"quartile":return e.Q;case"h":case"high":return e.H;default:throw new Error("Unknown EC Level: "+n)}}e.isValid=function(o){return o&&typeof o.bit<"u"&&o.bit>=0&&o.bit<4},e.from=function(o,r){if(e.isValid(o))return o;try{return t(o)}catch{return r}}})(Fe)),Fe}var qe,kt;function En(){if(kt)return qe;kt=1;function e(){this.buffer=[],this.length=0}return e.prototype={get:function(t){const n=Math.floor(t/8);return(this.buffer[n]>>>7-t%8&1)===1},put:function(t,n){for(let o=0;o>>n-o-1&1)===1)},getLengthInBits:function(){return this.length},putBit:function(t){const n=Math.floor(this.length/8);this.buffer.length<=n&&this.buffer.push(0),t&&(this.buffer[n]|=128>>>this.length%8),this.length++}},qe=e,qe}var Ve,At;function bn(){if(At)return Ve;At=1;function e(t){if(!t||t<1)throw new Error("BitMatrix size must be defined and greater than 0");this.size=t,this.data=new Uint8Array(t*t),this.reservedBit=new Uint8Array(t*t)}return e.prototype.set=function(t,n,o,r){const i=t*this.size+n;this.data[i]=o,r&&(this.reservedBit[i]=!0)},e.prototype.get=function(t,n){return this.data[t*this.size+n]},e.prototype.xor=function(t,n,o){this.data[t*this.size+n]^=o},e.prototype.isReserved=function(t,n){return this.reservedBit[t*this.size+n]},Ve=e,Ve}var Ke={},Lt;function kn(){return Lt||(Lt=1,(function(e){const t=se().getSymbolSize;e.getRowColCoords=function(o){if(o===1)return[];const r=Math.floor(o/7)+2,i=t(o),a=i===145?26:Math.ceil((i-13)/(2*r-2))*2,l=[i-7];for(let c=1;c=0&&r<=7},e.from=function(r){return e.isValid(r)?parseInt(r,10):void 0},e.getPenaltyN1=function(r){const i=r.size;let a=0,l=0,c=0,d=null,u=null;for(let f=0;f=5&&(a+=t.N1+(l-5)),d=m,l=1),m=r.get(p,f),m===u?c++:(c>=5&&(a+=t.N1+(c-5)),u=m,c=1)}l>=5&&(a+=t.N1+(l-5)),c>=5&&(a+=t.N1+(c-5))}return a},e.getPenaltyN2=function(r){const i=r.size;let a=0;for(let l=0;l=10&&(l===1488||l===93)&&a++,c=c<<1&2047|r.get(u,d),u>=10&&(c===1488||c===93)&&a++}return a*t.N3},e.getPenaltyN4=function(r){let i=0;const a=r.data.length;for(let c=0;c=0;){const a=i[0];for(let c=0;c0){const l=new Uint8Array(this.degree);return l.set(i,a),l}return i},We=t,We}var Je={},He={},Ye={},Rt;function Qt(){return Rt||(Rt=1,Ye.isValid=function(t){return!isNaN(t)&&t>=1&&t<=40}),Ye}var z={},It;function Zt(){if(It)return z;It=1;const e="[0-9]+",t="[A-Z $%*+\\-./:]+";let n="(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";n=n.replace(/u/g,"\\u");const o="(?:(?![A-Z0-9 $%*+\\-./:]|"+n+`)(?:.|[\r -]))+`;z.KANJI=new RegExp(n,"g"),z.BYTE_KANJI=new RegExp("[^A-Z0-9 $%*+\\-./:]+","g"),z.BYTE=new RegExp(o,"g"),z.NUMERIC=new RegExp(e,"g"),z.ALPHANUMERIC=new RegExp(t,"g");const r=new RegExp("^"+n+"$"),i=new RegExp("^"+e+"$"),a=new RegExp("^[A-Z0-9 $%*+\\-./:]+$");return z.testKanji=function(c){return r.test(c)},z.testNumeric=function(c){return i.test(c)},z.testAlphanumeric=function(c){return a.test(c)},z}var Pt;function ce(){return Pt||(Pt=1,(function(e){const t=Qt(),n=Zt();e.NUMERIC={id:"Numeric",bit:1,ccBits:[10,12,14]},e.ALPHANUMERIC={id:"Alphanumeric",bit:2,ccBits:[9,11,13]},e.BYTE={id:"Byte",bit:4,ccBits:[8,16,16]},e.KANJI={id:"Kanji",bit:8,ccBits:[8,10,12]},e.MIXED={bit:-1},e.getCharCountIndicator=function(i,a){if(!i.ccBits)throw new Error("Invalid mode: "+i);if(!t.isValid(a))throw new Error("Invalid version: "+a);return a>=1&&a<10?i.ccBits[0]:a<27?i.ccBits[1]:i.ccBits[2]},e.getBestModeForData=function(i){return n.testNumeric(i)?e.NUMERIC:n.testAlphanumeric(i)?e.ALPHANUMERIC:n.testKanji(i)?e.KANJI:e.BYTE},e.toString=function(i){if(i&&i.id)return i.id;throw new Error("Invalid mode")},e.isValid=function(i){return i&&i.bit&&i.ccBits};function o(r){if(typeof r!="string")throw new Error("Param is not a string");switch(r.toLowerCase()){case"numeric":return e.NUMERIC;case"alphanumeric":return e.ALPHANUMERIC;case"kanji":return e.KANJI;case"byte":return e.BYTE;default:throw new Error("Unknown mode: "+r)}}e.from=function(i,a){if(e.isValid(i))return i;try{return o(i)}catch{return a}}})(He)),He}var Mt;function _n(){return Mt||(Mt=1,(function(e){const t=se(),n=Gt(),o=lt(),r=ce(),i=Qt(),a=7973,l=t.getBCHDigit(a);function c(p,m,g){for(let v=1;v<=40;v++)if(m<=e.getCapacity(v,g,p))return v}function d(p,m){return r.getCharCountIndicator(p,m)+4}function u(p,m){let g=0;return p.forEach(function(v){const R=d(v.mode,m);g+=R+v.getBitsLength()}),g}function f(p,m){for(let g=1;g<=40;g++)if(u(p,g)<=e.getCapacity(g,m,r.MIXED))return g}e.from=function(m,g){return i.isValid(m)?parseInt(m,10):g},e.getCapacity=function(m,g,v){if(!i.isValid(m))throw new Error("Invalid QR Code version");typeof v>"u"&&(v=r.BYTE);const R=t.getSymbolTotalCodewords(m),C=n.getTotalCodewordsCount(m,g),_=(R-C)*8;if(v===r.MIXED)return _;const E=_-d(v,m);switch(v){case r.NUMERIC:return Math.floor(E/10*3);case r.ALPHANUMERIC:return Math.floor(E/11*2);case r.KANJI:return Math.floor(E/13);case r.BYTE:default:return Math.floor(E/8)}},e.getBestVersionForData=function(m,g){let v;const R=o.from(g,o.M);if(Array.isArray(m)){if(m.length>1)return f(m,R);if(m.length===0)return 1;v=m[0]}else v=m;return c(v.mode,v.getLength(),R)},e.getEncodedBits=function(m){if(!i.isValid(m)||m<7)throw new Error("Invalid QR Code version");let g=m<<12;for(;t.getBCHDigit(g)-l>=0;)g^=a<=0;)c^=t<0&&(i=this.data.substr(r),a=parseInt(i,10),o.put(a,l*3+1))},Ze=t,Ze}var Xe,Ut;function Rn(){if(Ut)return Xe;Ut=1;const e=ce(),t=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"," ","$","%","*","+","-",".","/",":"];function n(o){this.mode=e.ALPHANUMERIC,this.data=o}return n.getBitsLength=function(r){return 11*Math.floor(r/2)+6*(r%2)},n.prototype.getLength=function(){return this.data.length},n.prototype.getBitsLength=function(){return n.getBitsLength(this.data.length)},n.prototype.write=function(r){let i;for(i=0;i+2<=this.data.length;i+=2){let a=t.indexOf(this.data[i])*45;a+=t.indexOf(this.data[i+1]),r.put(a,11)}this.data.length%2&&r.put(t.indexOf(this.data[i]),6)},Xe=n,Xe}var et,Ft;function In(){if(Ft)return et;Ft=1;const e=ce();function t(n){this.mode=e.BYTE,typeof n=="string"?this.data=new TextEncoder().encode(n):this.data=new Uint8Array(n)}return t.getBitsLength=function(o){return o*8},t.prototype.getLength=function(){return this.data.length},t.prototype.getBitsLength=function(){return t.getBitsLength(this.data.length)},t.prototype.write=function(n){for(let o=0,r=this.data.length;o=33088&&i<=40956)i-=33088;else if(i>=57408&&i<=60351)i-=49472;else throw new Error("Invalid SJIS character: "+this.data[r]+` -Make sure your charset is UTF-8`);i=(i>>>8&255)*192+(i&255),o.put(i,13)}},tt=n,tt}var nt={exports:{}},Vt;function Mn(){return Vt||(Vt=1,(function(e){var t={single_source_shortest_paths:function(n,o,r){var i={},a={};a[o]=0;var l=t.PriorityQueue.make();l.push(o,0);for(var c,d,u,f,p,m,g,v,R;!l.empty();){c=l.pop(),d=c.value,f=c.cost,p=n[d]||{};for(u in p)p.hasOwnProperty(u)&&(m=p[u],g=f+m,v=a[u],R=typeof a[u]>"u",(R||v>g)&&(a[u]=g,l.push(u,g),i[u]=d))}if(typeof r<"u"&&typeof a[r]>"u"){var C=["Could not find a path from ",o," to ",r,"."].join("");throw new Error(C)}return i},extract_shortest_path_from_predecessor_list:function(n,o){for(var r=[],i=o;i;)r.push(i),n[i],i=n[i];return r.reverse(),r},find_path:function(n,o,r){var i=t.single_source_shortest_paths(n,o,r);return t.extract_shortest_path_from_predecessor_list(i,r)},PriorityQueue:{make:function(n){var o=t.PriorityQueue,r={},i;n=n||{};for(i in o)o.hasOwnProperty(i)&&(r[i]=o[i]);return r.queue=[],r.sorter=n.sorter||o.default_sorter,r},default_sorter:function(n,o){return n.cost-o.cost},push:function(n,o){var r={value:n,cost:o};this.queue.push(r),this.queue.sort(this.sorter)},pop:function(){return this.queue.shift()},empty:function(){return this.queue.length===0}}};e.exports=t})(nt)),nt.exports}var Kt;function $n(){return Kt||(Kt=1,(function(e){const t=ce(),n=xn(),o=Rn(),r=In(),i=Pn(),a=Zt(),l=se(),c=Mn();function d(C){return unescape(encodeURIComponent(C)).length}function u(C,_,E){const N=[];let D;for(;(D=C.exec(E))!==null;)N.push({data:D[0],index:D.index,mode:_,length:D[0].length});return N}function f(C){const _=u(a.NUMERIC,t.NUMERIC,C),E=u(a.ALPHANUMERIC,t.ALPHANUMERIC,C);let N,D;return l.isKanjiModeEnabled()?(N=u(a.BYTE,t.BYTE,C),D=u(a.KANJI,t.KANJI,C)):(N=u(a.BYTE_KANJI,t.BYTE,C),D=[]),_.concat(E,N,D).sort(function(L,A){return L.index-A.index}).map(function(L){return{data:L.data,mode:L.mode,length:L.length}})}function p(C,_){switch(_){case t.NUMERIC:return n.getBitsLength(C);case t.ALPHANUMERIC:return o.getBitsLength(C);case t.KANJI:return i.getBitsLength(C);case t.BYTE:return r.getBitsLength(C)}}function m(C){return C.reduce(function(_,E){const N=_.length-1>=0?_[_.length-1]:null;return N&&N.mode===E.mode?(_[_.length-1].data+=E.data,_):(_.push(E),_)},[])}function g(C){const _=[];for(let E=0;E=0&&k<=6&&(B===0||B===6)||B>=0&&B<=6&&(k===0||k===6)||k>=2&&k<=4&&B>=2&&B<=4?y.set(b+k,S+B,!0,!0):y.set(b+k,S+B,!1,!0))}}function g(y){const L=y.size;for(let A=8;A>k&1)===1,y.set(T,b,S,!0),y.set(b,T,S,!0)}function C(y,L,A){const w=y.size,T=u.getEncodedBits(L,A);let b,S;for(b=0;b<15;b++)S=(T>>b&1)===1,b<6?y.set(b,8,S,!0):b<8?y.set(b+1,8,S,!0):y.set(w-15+b,8,S,!0),b<8?y.set(8,w-b-1,S,!0):b<9?y.set(8,15-b-1+1,S,!0):y.set(8,15-b-1,S,!0);y.set(w-8,8,1,!0)}function _(y,L){const A=y.size;let w=-1,T=A-1,b=7,S=0;for(let k=A-1;k>0;k-=2)for(k===6&&k--;;){for(let B=0;B<2;B++)if(!y.isReserved(T,k-B)){let X=!1;S>>b&1)===1),y.set(T,k-B,X),b--,b===-1&&(S++,b=7)}if(T+=w,T<0||A<=T){T-=w,w=-w;break}}}function E(y,L,A){const w=new n;A.forEach(function(B){w.put(B.mode.bit,4),w.put(B.getLength(),f.getCharCountIndicator(B.mode,y)),B.write(w)});const T=e.getSymbolTotalCodewords(y),b=l.getTotalCodewordsCount(y,L),S=(T-b)*8;for(w.getLengthInBits()+4<=S&&w.put(0,4);w.getLengthInBits()%8!==0;)w.putBit(0);const k=(S-w.getLengthInBits())/8;for(let B=0;B=7&&R(B,L),_(B,S),isNaN(w)&&(w=a.getBestMask(B,C.bind(null,B,A))),a.applyMask(w,B),C(B,A,w),{modules:B,version:L,errorCorrectionLevel:A,maskPattern:w,segments:T}}return Ue.create=function(L,A){if(typeof L>"u"||L==="")throw new Error("No input text");let w=t.M,T,b;return typeof A<"u"&&(w=t.from(A.errorCorrectionLevel,t.M),T=d.from(A.version),b=a.from(A.maskPattern),A.toSJISFunc&&e.setToSJISFunction(A.toSJISFunc)),D(L,T,w,b)},Ue}var rt={},ot={},zt;function Xt(){return zt||(zt=1,(function(e){function t(n){if(typeof n=="number"&&(n=n.toString()),typeof n!="string")throw new Error("Color should be defined as hex string");let o=n.slice().replace("#","").split("");if(o.length<3||o.length===5||o.length>8)throw new Error("Invalid hex color: "+n);(o.length===3||o.length===4)&&(o=Array.prototype.concat.apply([],o.map(function(i){return[i,i]}))),o.length===6&&o.push("F","F");const r=parseInt(o.join(""),16);return{r:r>>24&255,g:r>>16&255,b:r>>8&255,a:r&255,hex:"#"+o.slice(0,6).join("")}}e.getOptions=function(o){o||(o={}),o.color||(o.color={});const r=typeof o.margin>"u"||o.margin===null||o.margin<0?4:o.margin,i=o.width&&o.width>=21?o.width:void 0,a=o.scale||4;return{width:i,scale:i?4:a,margin:r,color:{dark:t(o.color.dark||"#000000ff"),light:t(o.color.light||"#ffffffff")},type:o.type,rendererOpts:o.rendererOpts||{}}},e.getScale=function(o,r){return r.width&&r.width>=o+r.margin*2?r.width/(o+r.margin*2):r.scale},e.getImageWidth=function(o,r){const i=e.getScale(o,r);return Math.floor((o+r.margin*2)*i)},e.qrToImageData=function(o,r,i){const a=r.modules.size,l=r.modules.data,c=e.getScale(a,i),d=Math.floor((a+i.margin*2)*c),u=i.margin*c,f=[i.color.light,i.color.dark];for(let p=0;p=u&&m>=u&&p"u"&&(!a||!a.getContext)&&(c=a,a=void 0),a||(d=o()),c=t.getOptions(c);const u=t.getImageWidth(i.modules.size,c),f=d.getContext("2d"),p=f.createImageData(u,u);return t.qrToImageData(p.data,i,c),n(f,d,u),f.putImageData(p,0,0),d},e.renderToDataURL=function(i,a,l){let c=l;typeof c>"u"&&(!a||!a.getContext)&&(c=a,a=void 0),c||(c={});const d=e.render(i,a,c),u=c.type||"image/png",f=c.rendererOpts||{};return d.toDataURL(u,f.quality)}})(rt)),rt}var it={},Wt;function Fn(){if(Wt)return it;Wt=1;const e=Xt();function t(r,i){const a=r.a/255,l=i+'="'+r.hex+'"';return a<1?l+" "+i+'-opacity="'+a.toFixed(2).slice(1)+'"':l}function n(r,i,a){let l=r+i;return typeof a<"u"&&(l+=" "+a),l}function o(r,i,a){let l="",c=0,d=!1,u=0;for(let f=0;f0&&p>0&&r[f-1]||(l+=d?n("M",p+a,.5+m+a):n("m",c,0),c=0,d=!1),p+1':"",m="',g='viewBox="0 0 '+f+" "+f+'"',R=''+p+m+` -`;return typeof l=="function"&&l(null,R),R},it}var Jt;function qn(){if(Jt)return de;Jt=1;const e=Cn(),t=Dn(),n=Un(),o=Fn();function r(i,a,l,c,d){const u=[].slice.call(arguments,1),f=u.length,p=typeof u[f-1]=="function";if(!p&&!e())throw new Error("Callback required as last argument");if(p){if(f<2)throw new Error("Too few arguments provided");f===2?(d=l,l=a,a=c=void 0):f===3&&(a.getContext&&typeof d>"u"?(d=c,c=void 0):(d=c,c=l,l=a,a=void 0))}else{if(f<1)throw new Error("Too few arguments provided");return f===1?(l=a,a=c=void 0):f===2&&!a.getContext&&(c=l,l=a,a=void 0),new Promise(function(m,g){try{const v=t.create(l,c);m(i(v,a,c))}catch(v){g(v)}})}try{const m=t.create(l,c);d(null,i(m,a,c))}catch(m){d(m)}}return de.create=t.create,de.toCanvas=r.bind(null,n.render),de.toDataURL=r.bind(null,n.renderToDataURL),de.toString=r.bind(null,function(i,a,l){return o.render(i,l)}),de}var Vn=qn();const Kn=yn(Vn),s=e=>document.getElementById(e),jn=Array.from(document.querySelectorAll(".screen")),M=s("notice");let Ne="",fe="",ge="",ie="",h,dt,Te="held",K=1,ae=0;const ve=8;let x,J=[],Z,P,_e,en="activity",Y,we="",oe="";const he=20,zn={1:"Mining Reward",2:"Transfer",3:"Token Creation",4:"NFT/RWA Creation",5:"Marketing",6:"Swap",7:"Loan",8:"Loan Payment",9:"Collateral Claim",10:"Asset Burn",11:"Token Issuance",12:"Vanity Address",100:"Storage Key",101:"Data Storage Bool",102:"Data Storage U8",103:"Data Storage U16",104:"Data Storage U32",105:"Data Storage U64",106:"Data Storage U128",107:"Data Storage String",108:"Data Storage I8",109:"Data Storage I16",110:"Data Storage I32",111:"Data Storage I64",112:"Data Storage I128",113:"Delete Stored Data",200:"Proposal",201:"Proposal Vote",202:"Activation Vote"};async function $(e,t={}){const n=await chrome.runtime.sendMessage({type:e,...t});if(!(n!=null&&n.ok))throw new Error((n==null?void 0:n.error)??"Wallet request failed.");return n.result}function I(e,t=!0){jn.forEach(n=>{n.hidden=n.id!==e}),t&&(M.textContent="")}function V(e){var i;h=e;const t=e.address??((i=e.wallets.find(a=>a.active))==null?void 0:i.address),n=(t==null?void 0:t.endsWith(".cltc"))??!0,o=n?"Testnet":"Mainnet",r=n?"CLTC":"CLC";document.querySelectorAll("[data-network-name]").forEach(a=>{a.textContent=o}),document.querySelectorAll("[data-network-symbol]").forEach(a=>{a.textContent=r}),s("base-asset-name").textContent=`Contractless ${o}`,s("wallet-address").textContent=e.address??"",s("wallet-address-short").textContent=e.address?`${e.address.slice(0,6)}...${e.address.slice(-6)}`:"Account",s("settings-api-url").value=e.apiUrl,s("settings-lock-timeout").value=String(e.autoLockMinutes),Zn(e),e.exists?e.unlocked?at().then(a=>{a||(I("dashboard-screen"),Be())}):I("locked-screen"):I("create-screen")}function On(e,t){return e==="contractless_connect"?"Connect application":e==="contractless_signMessage"?"Sign text message":e==="contractless_sendTransaction"||e==="contractless_signDualTransaction"?`Sign ${String(t.transaction_type??"transaction")}`:"Review request"}function j(e,t,n){const o=document.createElement("dt");o.textContent=t.replaceAll("_"," ");const r=document.createElement("dd");r.textContent=typeof n=="object"?JSON.stringify(n,null,2):String(n),e.append(o,r)}function te(e,t,n,o){const r=re(e[t]),i=String(e[n]??"").trim().toUpperCase(),a=Number(e[o]??0);return`${r} ${i}${a>0?` #${a}`:""}`}function Ht(e,t,n){var i;const o=n===1?2:1,r=(i=h==null?void 0:h.address)!=null&&i.endsWith(".cltc")?"CLTC":"CLC";j(e,"Your miner tip",te(t,`tip${n}`,`ticker${n}`,`nft_series${n}`)),j(e,"Your transaction fee",`${re(t[`txfee${n}`])} ${r}`),j(e,"Other party miner tip",te(t,`tip${o}`,`ticker${o}`,`nft_series${o}`)),j(e,"Other party transaction fee",`${re(t[`txfee${o}`])} ${r}`)}function Wn(e,t){var a;const n=((a=h==null?void 0:h.address)==null?void 0:a.trim().toLowerCase())??"",o=String(t.sender1??"").trim().toLowerCase(),r=String(t.sender2??"").trim().toLowerCase(),i=n===o?1:n===r?2:0;if(i===1){j(e,"Sending",te(t,"value1","ticker1","nft_series1")),j(e,"Receiving",te(t,"value2","ticker2","nft_series2")),Ht(e,t,1);return}if(i===2){j(e,"Sending",te(t,"value2","ticker2","nft_series2")),j(e,"Receiving",te(t,"value1","ticker1","nft_series1")),Ht(e,t,2);return}j(e,"First party sending",te(t,"value1","ticker1","nft_series1")),j(e,"Second party sending",te(t,"value2","ticker2","nft_series2"))}function ye(e){const t=s("approve-provider-approval"),n=s("reject-provider-approval"),o=e!==null;t.disabled=o,n.disabled=o,t.classList.toggle("is-processing",e==="approve"),n.classList.toggle("is-processing",e==="reject"),t.textContent=e==="approve"?"Processing...":"Approve",n.textContent=e==="reject"?"Rejecting...":"Reject"}async function at(){const e=await $("pending-provider-approval");if(!(e!=null&&e.request))return!1;const t=e.request;ye(null),oe=t.id;const n=(e.total??0)>1?` · Request ${e.position??1} of ${e.total}`:"";s("provider-approval-origin").textContent=`${t.origin}${n}`;const o=s("provider-approval-risk");o.className=`risk-label risk-${t.risk}`,o.textContent=t.risk==="safe"?"Safe":t.risk==="low"?"Low risk":"High risk";const r=t.display??{},i=t.method==="contractless_sendTransaction"||t.method==="contractless_signDualTransaction";s("provider-approval-title").textContent=On(t.method,r),s("provider-approval-intro").textContent=i?"Review every transaction field before signing.":"Review this request before approving it.";const a=s("provider-approval-details");return a.replaceChildren(),Object.entries(r).forEach(([l,c])=>{if(l==="transaction_fields"&&c&&typeof c=="object"){const d=c,u=Number(d.txtype??0),f=new Set(["ticker1","nft_series1","value1","ticker2","nft_series2","value2","tip1","tip2","txfee1","txfee2"]);u===6&&Wn(a,d),Object.entries(d).forEach(([p,m])=>{u===6&&f.has(p)||j(a,p==="txtype"?"transaction_type_id":p,ln(u,p,m))});return}j(a,l,c)}),I("provider-approval-screen"),!0}async function tn(e,t){if(!(e>0&&await at())){if(t){const n=Date.now()+1500;for(;Date.now()setTimeout(o,75))}}window.close()}}function Jn(e){return e.replace(/[.0]/g,"").length>0}function st(){var c;const e=s("token-list");if(e.replaceChildren(),!x){const d=document.createElement("div");d.className="empty-assets";const u=document.createElement("strong");u.textContent="Loading token balances...";const f=document.createElement("span");f.textContent="Balances are retrieved from the selected Contractless API.",d.append(u,f),e.append(d);return}const t=(c=h==null?void 0:h.address)!=null&&c.endsWith(".cltc")?"CLTC":"CLC",n=new Set(x.tokens.map(d=>d.token.trim().toUpperCase())),o=new Set(x.nfts.map(d=>`${d.name.trim().toUpperCase()}|${Number(d.series||0)}`)),r=x.balances.filter(d=>{const u=d.asset.trim().toUpperCase(),f=`${u}|${Number(d.nft_series||0)}`;return d.nft_series===0&&u!=="CLTC"&&u!=="CLC"&&n.has(u)&&!o.has(f)}),i=new Map(r.map(d=>[d.asset.trim().toUpperCase(),d])),a=Te==="all"?x.tokens.map(d=>d.token):r.filter(d=>Jn(d.balance)).map(d=>d.asset),l=[...new Set(a.map(d=>d.trim().toUpperCase()))].filter(d=>d!==t&&!o.has(`${d}|0`)).sort((d,u)=>d.localeCompare(u));if(l.length===0){const d=document.createElement("div");d.className="empty-assets";const u=document.createElement("strong");u.textContent=Te==="held"?"No token balances found":"No tokens found";const f=document.createElement("span");f.textContent=Te==="held"?"Switch to All tokens to view the complete network token list.":x.tokenCatalogError?`Token catalog unavailable: ${x.tokenCatalogError}`:"The selected API did not return any fungible tokens.",d.append(u,f),e.append(d);return}l.forEach(d=>{const u=i.get(d),f=document.createElement("div");f.className="asset-row";const p=document.createElement("div");p.className="asset-symbol token-symbol",p.textContent=d.slice(0,3);const m=document.createElement("div");m.className="asset-name";const g=document.createElement("strong");g.textContent=d;const v=document.createElement("span");v.textContent="Contractless token",m.append(g,v);const R=document.createElement("div");R.className="asset-value";const C=document.createElement("strong");C.textContent=(u==null?void 0:u.balance)??"0.00000000";const _=document.createElement("span");_.textContent=d,R.append(C,_),f.append(p,m,R),e.append(f)})}async function Be(){var e;if(h!=null&&h.unlocked){x=void 0,s("base-balance").textContent="--",s("base-asset-balance").textContent="--",st();try{const t=await $("wallet-balances");x={balances:Array.isArray(t.balances)?t.balances:[],tokens:Array.isArray(t.tokens)?t.tokens:[],nfts:Array.isArray(t.nfts)?t.nfts:[],tokenCatalogError:t.tokenCatalogError,nftCatalogError:t.nftCatalogError};const n=(e=h.address)!=null&&e.endsWith(".cltc")?"CLTC":"CLC",o=x.balances.find(i=>i.nft_series===0&&i.asset.toUpperCase()===n),r=(o==null?void 0:o.balance)??"0.00000000";s("base-balance").textContent=r,s("base-asset-balance").textContent=r,st()}catch(t){const n=s("token-list");n.replaceChildren();const o=document.createElement("div");o.className="empty-assets balance-error";const r=document.createElement("strong");r.textContent="Unable to load balances";const i=document.createElement("span");i.textContent=q(t),o.append(r,i),n.append(o),M.textContent=q(t)}}}function Le(e,t){return`${e.trim().toUpperCase()}|${t}`}function Hn(e){try{return H(e,"Balance")>0n}catch{return!1}}function nn(e){if(e.ownership_type!==1)return"Complete ownership";try{const t=H(e.balance,"Balance"),n=H(e.supply,"Supply");if(n<=0n)return"0% ownership";const o=t*100000000n/n,r=o/1000000n,i=(o%1000000n).toString().padStart(6,"0").replace(/0+$/,"");return`${r}${i?`.${i}`:""}% ownership`}catch{return"Fractional ownership"}}function ut(e){var t;return(t=e.details)!=null&&t.metadata&&typeof e.details.metadata=="object"?e.details.metadata:{}}function ft(e){const t=ut(e).name;return typeof t=="string"&&t.trim()?t.trim():e.series>0?`${e.name} #${e.series}`:e.name}function rn(e){const n=ut(e).contractless;return n&&typeof n=="object"&&String(n.metadata_type??"").toLowerCase()==="rwa"?"RWA":"NFT"}function be(e){return e.series>0?`${e.name}_${e.series}`:e.name}function Yn(e,t=7,n=7){return e.length>t+n+3?`${e.slice(0,t)}...${e.slice(-n)}`:e}function Gn(e,t){var r;const n=document.createElement("div");if(n.className=t,(r=e.details)!=null&&r.image_data_url){const i=document.createElement("img");return i.src=e.details.image_data_url,i.alt=ft(e),n.append(i),n}const o=document.createElement("span");return o.textContent=e.loading?"...":e.name.slice(0,2).toUpperCase(),n.append(o),n}function on(){const e=(K-1)*ve;return J.slice(e,e+ve)}function Ce(){const e=s("nfts-list");e.replaceChildren();const t=Math.max(1,Math.ceil(J.length/ve));if(K=Math.min(Math.max(1,K),t),s("nfts-count").textContent=J.length===1?"1 owned asset":`${J.length} owned assets`,s("nfts-page").textContent=String(K),s("nfts-pages").textContent=String(t),s("nfts-pagination").hidden=t<=1,s("nfts-previous").disabled=K<=1,s("nfts-next").disabled=K>=t,!J.length){const n=document.createElement("div");n.className="nfts-empty";const o=document.createElement("strong");o.textContent="No NFTs or RWAs found";const r=document.createElement("span");r.textContent=x!=null&&x.nftCatalogError?`NFT catalog unavailable: ${x.nftCatalogError}`:"Assets owned by this wallet will appear here.",n.append(o,r),e.append(n);return}on().forEach(n=>{const o=document.createElement("button");o.type="button",o.className="nft-card",o.append(Gn(n,"nft-card-media"));const r=document.createElement("div");r.className="nft-card-identity";const i=document.createElement("span");i.textContent=rn(n);const a=document.createElement("strong");a.textContent=ft(n);const l=document.createElement("small");l.textContent=be(n);const c=document.createElement("b");if(c.textContent=nn(n),r.append(i,a,l,c),n.error){const d=document.createElement("em");d.textContent="Media unavailable",r.append(d)}o.append(r),o.addEventListener("click",()=>Qn(n)),e.append(o)})}function Se(e,t,n){const o=document.createElement("div"),r=document.createElement("dt");r.textContent=t;const i=document.createElement("dd");i.textContent=n||"--",o.append(r,i),e.append(o)}function xe(e){Z=e;const t=e.details,n=ut(e),o=rn(e),r=ft(e);s("nft-detail-title").textContent=r,s("nft-detail-kind").textContent=`${o} details`,s("nft-detail-badge").textContent=o,s("nft-detail-name").textContent=r,s("nft-detail-ownership").textContent=nn(e);const i=s("nft-detail-image");i.src=(t==null?void 0:t.image_data_url)??"",i.alt=r,i.hidden=!(t!=null&&t.image_data_url);const a=n.description??n.summary;s("nft-detail-description").textContent=typeof a=="string"&&a.trim()?a.trim():t?"No description was included in the NFT metadata.":"Loading NFT metadata and provenance...";const l=s("nft-detail-attributes");l.replaceChildren(),(Array.isArray(n.attributes)?n.attributes.slice(0,12):[]).forEach(f=>{if(!f||typeof f!="object")return;const p=f,m=document.createElement("div"),g=document.createElement("span");g.textContent=String(p.trait_type??p.type??"Attribute");const v=document.createElement("strong");v.textContent=String(p.value??""),m.append(g,v),l.append(m)}),l.hidden=l.childElementCount===0;const d=s("nft-detail-fields");d.replaceChildren(),Se(d,"Asset",be(e)),Se(d,"Creator",(t==null?void 0:t.creator)??"--"),Se(d,"IPFS CID",(t==null?void 0:t.item_ipfs)??"--"),Se(d,"Origin transaction",(t==null?void 0:t.genesis_txid)??e.origin_txid);const u=s("nft-detail-history");if(u.replaceChildren(),t)if(t.history.length)t.history.slice().reverse().forEach(f=>{const p=document.createElement("button");p.type="button",p.className="nft-history-row",p.title=`View full transaction ${f.txid}`;const m=document.createElement("strong");m.textContent=f.action;const g=document.createElement("span");g.textContent=`Block ${Number(f.block).toLocaleString()}`;const v=document.createElement("small");v.textContent=Yn(f.txid),p.append(m,g,v),p.addEventListener("click",()=>{un({txid:f.txid,block_height:Number(f.block),transaction_hex:""},"nft")}),u.append(p)});else{const f=document.createElement("p");f.textContent="No provenance records were returned.",u.append(f)}else{const f=document.createElement("p");f.textContent="Loading provenance...",u.append(f)}}function Qn(e){xe(e),I("nft-detail-screen")}async function mt(e){const t=on().filter(r=>!r.details&&!r.loading);let n=0;const o=async()=>{for(;n[Le(r.name,r.series),r]));J=x.nfts.map(r=>{const i=x==null?void 0:x.balances.find(l=>Le(l.asset,Number(l.nft_series||0))===Le(r.name,Number(r.series||0)));if(!i||!Hn(i.balance))return null;const a=n.get(Le(r.name,r.series));return{name:r.name.trim(),series:Number(r.series||0),origin_txid:r.origin_txid,ownership_type:Number(r.ownership_type||0),supply:r.supply,balance:i.balance,details:a==null?void 0:a.details,error:a==null?void 0:a.error}}).filter(r=>r!==null).sort((r,i)=>r.name.localeCompare(i.name)||r.series-i.series);const o=Math.max(1,Math.ceil(J.length/ve));K=Math.min(K,o),Ce(),await mt(t)}function Zn(e){const t=s("known-addresses");t.replaceChildren(),e.wallets.forEach(n=>{const o=document.createElement("div");o.className=`known-address${n.active?" active-address":""}`;const r=document.createElement("button");r.type="button",r.className="address-select",r.dataset.walletId=n.id;const i=document.createElement("span");i.className="address-avatar";const a=document.createElement("img");a.src=chrome.runtime.getURL("contractless-logo.png"),a.alt="",i.append(a);const l=document.createElement("span");l.className="address-details";const c=document.createElement("strong");c.textContent=n.label;const d=document.createElement("small");d.textContent=n.address,l.append(c,d);const u=document.createElement("span");u.className="selected-mark",u.textContent=n.active?"✓":"",r.append(i,l,u),r.addEventListener("click",()=>{if(n.active){G(!1);return}U(async()=>{G(!1),fe="",ie="",V(await $("switch-wallet",{walletId:n.id}))})});const f=document.createElement("button");f.type="button",f.className="rename-address",f.title="Rename wallet",f.setAttribute("aria-label",`Rename ${n.label}`),f.textContent="✎",f.addEventListener("click",()=>{const p=window.prompt("Wallet label",n.label);p===null||p.trim()===n.label||U(async()=>{const m=await $("rename-wallet",{walletId:n.id,label:p});V(m),G(!0)})}),o.append(r,f),t.append(o)})}function G(e){const t=s("account-drawer"),n=s("drawer-backdrop"),o=s("account-menu-button");t.classList.toggle("open",e),t.setAttribute("aria-hidden",String(!e)),o.setAttribute("aria-expanded",String(e)),n.hidden=!e}function gt(){s("revealed-private-key").value="",s("private-key-result").hidden=!0}function Ee(e){if(s("backup-key-modal").hidden=!e,s("backup-key-backdrop").hidden=!e,e){const t=s("backup-key-input");t.value="",t.focus()}else s("backup-key-input").value="",dt=void 0}async function Xn(){const e=await $("wallet-receive-address"),t=String(e.receiveAddress??"");if(!t)throw new Error("No active wallet address is available.");s("receive-address-label").textContent=e.vanity?"Vanity address":"Wallet address",s("receive-address-value").textContent=t;const n=s("receive-qr");await Kn.toCanvas(n,t,{width:220,margin:1,errorCorrectionLevel:"M",color:{dark:"#071016",light:"#ffffff"}}),I("receive-screen")}function H(e,t){const n=e.trim();if(!/^(?:0|[1-9]\d*)(?:\.\d{1,8})?$/.test(n))throw new Error(`${t} must be a positive number with no more than 8 decimal places.`);const[o,r=""]=n.split(".");return BigInt(o)*100000000n+BigInt(r.padEnd(8,"0"))}function ne(e){const t=e/100000000n,n=(e%100000000n).toString().padStart(8,"0");return`${t}.${n}`}function an(){if(P)return P.balance;const e=s("send-asset").value,t=x==null?void 0:x.balances.find(n=>n.nft_series===0&&n.asset.trim().toUpperCase()===e);return(t==null?void 0:t.balance)??"0.00000000"}function sn(){var o;const e=s("send-asset").value,t=(o=h==null?void 0:h.address)!=null&&o.endsWith(".cltc")?"CLTC":"CLC";if(e!==t)return 100000000n;const n=s("send-amount").value.trim();if(!n)return 0n;try{return(H(n,"Amount")+99n)/100n}catch{return 0n}}function Re(){var r;const e=(P==null?void 0:P.name)??s("send-asset").value,t=(r=h==null?void 0:h.address)!=null&&r.endsWith(".cltc")?"CLTC":"CLC",n=P?be(P):e;s("send-amount-symbol").textContent=n,s("send-available").textContent=`Available: ${an()} ${n}`;const o=sn();s("send-fee").value=ne(o),s("send-fee-note").textContent=!P&&e===t?"Minimum fee: 1% of the transfer amount.":`Minimum fee: 1 ${t} for asset transfers.`}function er(){var o;const e=s("send-asset");e.replaceChildren();const t=(o=h==null?void 0:h.address)!=null&&o.endsWith(".cltc")?"CLTC":"CLC",n=new Set([t]);x==null||x.tokens.forEach(r=>{const i=r.token.trim().toUpperCase();(x==null?void 0:x.balances.find(l=>l.nft_series===0&&l.asset.trim().toUpperCase()===i&&H(l.balance,"Balance")>0n))&&n.add(i)}),n.forEach(r=>{const i=document.createElement("option");i.value=r,i.textContent=r,e.append(i)}),Re()}function tr(){if(!x)throw new Error("Wallet balances are still loading.");P=void 0,Y=void 0,s("send-form").reset(),s("send-asset").disabled=!1,s("send-amount").disabled=!1,er(),I("send-screen")}function nr(e){if(!x)throw new Error("Wallet balances are still loading.");P=e,Y=void 0,s("send-form").reset();const t=s("send-asset");t.replaceChildren();const n=document.createElement("option");n.value=e.name,n.textContent=be(e),t.append(n),t.disabled=!0;const o=s("send-amount");e.ownership_type===0?(o.value="1.00000000",o.disabled=!0):(o.value="",o.disabled=!1),Re(),I("send-screen")}async function rr(){var v;if(!(h!=null&&h.address))throw new Error("No active wallet is available.");const e=(P==null?void 0:P.name)??s("send-asset").value,t=P?be(P):e,n=Q(s("send-recipient").value,"Enter a receiving address."),o=Q(s("send-amount").value,"Enter an amount to send."),r=Q(s("send-fee").value,"Enter a transaction fee."),i=H(o,"Amount"),a=H(r,"Transaction fee");if(i===0n)throw new Error("The transfer amount must be greater than zero.");if((P==null?void 0:P.ownership_type)===0&&i!==100000000n)throw new Error("An indivisible NFT must be transferred as one complete asset.");if((P==null?void 0:P.ownership_type)===1&&i>100000000n)throw new Error("A fractional NFT/RWA transfer cannot exceed one complete asset.");const l=sn();if(ac)throw new Error(`Insufficient ${e} balance.`);const d=h.address.endsWith(".cltc")?"CLTC":"CLC",u=((v=x==null?void 0:x.balances.find(R=>R.nft_series===0&&R.asset.trim().toUpperCase()===d))==null?void 0:v.balance)??"0.00000000",f=H(u,"Base balance");if((e===d?i+a:a)>f)throw new Error(`Insufficient ${d} balance including the fee.`);const m=await $("wallet-prepare-transfer",{receiver:n,asset:e,nftSeries:(P==null?void 0:P.series)??0,valueAtomic:i.toString(),feeAtomic:a.toString()}),g=e===d?`${ne(i+a)} ${d}`:`${ne(i)} ${t} + ${ne(a)} ${d}`;Y={transaction:m.transaction,receiverInput:m.receiverInput,asset:e,amount:ne(i),fee:ne(a),total:g},s("review-amount").textContent=Y.amount,s("review-asset").textContent=t,s("review-sender").textContent=h.address,s("review-recipient").textContent=m.receiverInput,s("review-resolved-recipient").textContent=String(m.review.receiver??""),s("review-fee").textContent=Y.fee,s("review-total").textContent=g,I("send-review-screen")}function cn(e){if(!/^[0-9a-f]+$/i.test(e)||e.length<10)return;const t=e.slice(2,10).match(/../g);if(!t||t.length!==4)return;const n=t.reduce((r,i,a)=>r+Number.parseInt(i,16)*2**(a*8),0),o=new Date(n*1e3);return Number.isNaN(o.getTime())?void 0:o}function or(e){return e.split("_").map(t=>t&&`${t[0].toUpperCase()}${t.slice(1)}`).join(" ")}function re(e){try{const t=ne(BigInt(String(e??"0"))),[n,o]=t.split("."),r=o.replace(/0+$/,"");return r?`${n}.${r}`:`${n}.0`}catch{return String(e??"")}}function ir(e,t){var o;return t.startsWith("txfee")?!0:((o={1:new Set(["value"]),2:new Set(["value"]),3:new Set(["number"]),6:new Set(["value1","value2","tip1","tip2"]),7:new Set(["loan_amount","collateral_amount","payment_amount","max_late_value"]),8:new Set(["payback_amount","tip"]),10:new Set(["value"]),11:new Set(["number"])}[e])==null?void 0:o.has(t))??!1}function ln(e,t,n){if(typeof n=="boolean")return n?"True":"False";if(ir(e,t))return re(n);if(t==="time"||t==="timestamp"||t==="offer_expiration"){const o=Number(n);if(Number.isFinite(o))return`${new Date(o*1e3).toLocaleString()} (${o})`}return t==="payment_period"?{d:"Daily",w:"Weekly",m:"Monthly"}[String(n).trim().toLowerCase()]??String(n??""):e===3&&t==="hard_limit"?Number(n)===1?"Yes":"No":e===4&&t==="series"?Number(n)===1?"Series":"Single NFT/RWA":e===4&&t==="ownership_type"?Number(n)===1?"Fractional ownership":"Complete ownership":(e===201||e===202)&&t==="vote"?Number(n)===1?"Approve":"Reject":(t==="previous"||t.endsWith("_hash"))&&/^0+$/.test(String(n))?"None":e===5&&(t==="impression_value"||t==="click_value")?(Number(n)/100).toFixed(2):typeof n=="string"?n.trim():String(n??"")}function F(e,t,n,o=!1,r=0){const i=document.createElement("div");i.className=`transaction-field${o?" technical-field":""}`;const a=document.createElement("span");a.textContent=or(t);const l=document.createElement("strong");l.textContent=o?String(n??""):ln(r,t,n),i.append(a,l),e.append(i)}function ht(e,t){return!e||!t||t=he?`${n} confirmations`:`${n}/${he} confirmations`:`Pending · 0/${he} confirmations`}async function un(e,t="activity"){_e=e,en=t;const n=s("close-transaction");n.title=t==="nft"?"Back to NFT/RWA details":"Back to activity",n.setAttribute("aria-label",t==="nft"?"Back to NFT/RWA details":"Back to activity"),I("transaction-screen"),s("transaction-title").textContent="Loading transaction",s("transaction-header-status").textContent="",s("transaction-full-txid").textContent=e.txid,s("transaction-overview").replaceChildren(),s("transaction-fields").replaceChildren(),s("transaction-technical-fields").replaceChildren(),s("transaction-miner-earnings").replaceChildren(),s("miner-earnings-section").hidden=!0;try{const o=await $("wallet-transaction",{txid:e.txid}),r=await Yt(),i=JSON.parse(r.decode_transaction(o.transaction_hex)),l=ht(o.block_height,o.current_height){F(u,m,g,!1,i.txtype)});const f=e.miner_earnings??[];if(f.length>0){const m=s("transaction-miner-earnings");f.forEach((g,v)=>{F(m,`earning_${v+1}_type`,g.type),F(m,`earning_${v+1}_asset`,g.asset),F(m,`earning_${v+1}_nft_series`,g.nft_series),F(m,`earning_${v+1}_amount`,`${re(g.amount_atomic)} ${g.asset.trim()}`)}),s("miner-earnings-section").hidden=!1}const p=s("transaction-technical-fields");i.stored_hash&&F(p,"stored_hash",i.stored_hash,!0),i.signature&&F(p,"signature",i.signature,!0),i.signature1&&F(p,"signature_1",i.signature1,!0),i.signature2&&F(p,"signature_2",i.signature2,!0),F(p,"raw_transaction_bytes",o.transaction_hex,!0)}catch(o){s("transaction-title").textContent="Transaction unavailable";const r=s("transaction-fields");r.replaceChildren(),F(r,"error",q(o))}}function ue(e){const t=String(e??"").trim();return t.length>18?`${t.slice(0,8)}...${t.slice(-7)}`:t}function ar(e,t){const n=e.fields,o=t.trim().toLowerCase(),r=o.endsWith(".cltc")?"CLTC":"CLC",i=c=>String(n[c]??"").trim(),a=(c,d,u="")=>`${u}${re(n[c])} ${d}`,l=()=>`-${re(n.txfee??0)} ${r}`;switch(e.txtype){case 1:return{title:"Mining reward",subtitle:"From network",amount:a("value",r,"+"),direction:"incoming"};case 2:{const c=i("coin"),d=String(n.sender??"").trim().toLowerCase()===o;return{title:d?`Sent ${c}`:`Received ${c}`,subtitle:d?`To: ${ue(n.receiver)}`:`From: ${ue(n.sender)}`,amount:a("value",c,d?"-":"+"),direction:d?"outgoing":"incoming"}}case 3:{const c=i("ticker");return{title:`Created ${c}`,subtitle:"Token creation",amount:a("number",c,"+"),secondary:l(),direction:"incoming"}}case 4:{const c=String(n.count??"1");return{title:`Created ${i("nft_name")}`,subtitle:Number(n.series??0)===0?"NFT/RWA":"NFT/RWA collection",amount:`+${c} ${Number(c)===1?"item":"items"}`,secondary:l(),direction:"incoming"}}case 6:{const c=String(n.sender1??"").trim().toLowerCase()===o,d=i(c?"ticker1":"ticker2"),u=i(c?"ticker2":"ticker1");return{title:"Completed swap",subtitle:`With: ${ue(n[c?"sender2":"sender1"])}`,amount:a(c?"value1":"value2",d,"-"),secondary:a(c?"value2":"value1",u,"+"),direction:"neutral"}}case 7:{const c=String(n.lender??"").trim().toLowerCase()===o;return{title:c?"Loan funded":"Loan received",subtitle:c?`To: ${ue(n.borrower)}`:`From: ${ue(n.lender)}`,amount:a("loan_amount",i("loan_coin"),c?"-":"+"),direction:c?"outgoing":"incoming"}}case 8:return{title:"Loan payment",subtitle:`Contract: ${ue(n.contract_hash)}`,amount:`-${re(n.payback_amount)}`,direction:"outgoing"};case 10:return{title:`Burned ${i("coin")}`,subtitle:"Removed from supply",amount:a("value",i("coin"),"-"),direction:"outgoing"};case 11:{const c=i("ticker");return{title:`Issued ${c}`,subtitle:"Additional token supply",amount:a("number",c,"+"),secondary:l(),direction:"incoming"}}case 12:return{title:"Created vanity address",subtitle:String(n.vanity_address??"").trim(),amount:l(),direction:"outgoing"};default:return{title:e.transaction_name,subtitle:"Contractless transaction",amount:l(),direction:"outgoing"}}}async function sr(e,t){const n=s("activity-list");if(n.replaceChildren(),s("activity-count").textContent=`${e.length} shown`,e.length===0){const r=document.createElement("div");r.className="activity-empty";const i=document.createElement("strong");i.textContent="No wallet activity found";const a=document.createElement("span");a.textContent="New transactions will appear here after they reach the selected API.",r.append(i,a),n.append(r);return}const o=await Yt();e.forEach(r=>{let i;try{i=JSON.parse(o.decode_transaction(r.transaction_hex))}catch{const E=Number.parseInt(r.transaction_hex.slice(0,2),16);i={txtype:E,transaction_name:zn[E]??`Transaction Type ${E}`,fields:{}}}const a=ar(i,(h==null?void 0:h.address)??""),l=cn(r.transaction_hex),d=ht(r.block_height,t){un(r)}),n.append(u)})}async function fn(){if(!(h!=null&&h.unlocked))return;s("activity-count").textContent="Loading";const e=s("activity-list");e.replaceChildren();const t=document.createElement("div");t.className="activity-empty",t.textContent="Loading recent activity...",e.append(t);try{const n=await $("wallet-activity");await sr(Array.isArray(n.transactions)?n.transactions:[],Number(n.current_height??0))}catch(n){e.replaceChildren();const o=document.createElement("div");o.className="activity-empty activity-error",o.textContent=q(n),e.append(o),s("activity-count").textContent="Unavailable"}}function q(e){return e instanceof Error?e.message:String(e).replace(/^JsValue\((.*)\)$/,"$1")}async function U(e,t=!1){M.textContent="",t&&I("loading");try{await e()}catch(n){throw M.textContent=q(n),n}}function Q(e,t){if(!e.trim())throw new Error(t);return e}function cr(e){let t="";for(let o=0;oURL.revokeObjectURL(r),1e3)}async function pn(e,t){h=e,fe=t,ie=String(await $("export-private-key-image",{password:t,imagePassword:t})),s("wallet-image-preview").src=`data:image/png;base64,${ie}`;const n=s("backup-confirmed");n.disabled=!0,n.checked=!1,s("open-wallet").disabled=!0,I("backup-screen")}document.querySelectorAll(".navigation").forEach(e=>{e.addEventListener("click",()=>I(String(e.dataset.screen)))});s("account-menu-button").addEventListener("click",()=>G(!0));s("close-account-drawer").addEventListener("click",()=>G(!1));s("drawer-backdrop").addEventListener("click",()=>G(!1));function gn(e){G(!1),s("cancel-wallet-add").hidden=!1,I(e)}s("menu-create-wallet").addEventListener("click",()=>{gn("create-screen")});s("menu-import-wallet").addEventListener("click",()=>{gn("image-screen")});s("cancel-wallet-add").addEventListener("click",()=>{s("cancel-wallet-add").hidden=!0,h&&V(h)});s("menu-settings").addEventListener("click",()=>{G(!1),gt(),h&&(s("settings-api-url").value=h.apiUrl,s("settings-lock-timeout").value=String(h.autoLockMinutes)),I("settings-screen")});s("close-settings").addEventListener("click",()=>{gt(),h&&V(h)});s("drawer-lock-wallet").addEventListener("click",()=>{U(async()=>{G(!1),fe="",ie="",V(await $("lock"))})});s("open-receive").addEventListener("click",()=>{U(Xn)});s("open-send").addEventListener("click",()=>{U(async()=>tr())});s("close-send").addEventListener("click",()=>{Y=void 0,P?(xe(P),I("nft-detail-screen")):h&&V(h)});s("send-asset").addEventListener("change",Re);s("send-amount").addEventListener("input",Re);s("send-form").addEventListener("submit",e=>{e.preventDefault(),U(rr)});s("send-form").addEventListener("keydown",e=>{!(e instanceof KeyboardEvent)||e.key!=="Enter"||e.target instanceof HTMLInputElement&&(e.preventDefault(),s("send-form").requestSubmit())});s("edit-send").addEventListener("click",()=>{I("send-screen")});s("sign-broadcast-transfer").addEventListener("click",()=>{U(async()=>{if(!Y)throw new Error("The reviewed transfer is unavailable.");we=(await $("wallet-broadcast-transfer",{transaction:Y.transaction})).txid,s("send-result-txid").textContent=we,Y=void 0,I("send-success-screen")})});s("copy-send-txid").addEventListener("click",()=>{we&&navigator.clipboard.writeText(we).then(()=>{M.textContent="Transaction ID copied."}).catch(e=>{M.textContent=q(e)})});s("finish-send").addEventListener("click",()=>{we="";const e=!!P;P=void 0,h&&(Be(),e?(Z=void 0,I("nfts-screen"),pt(!0)):V(h))});s("open-activity").addEventListener("click",()=>{I("activity-screen"),fn()});s("open-nfts").addEventListener("click",()=>{K=1,Z=void 0,I("nfts-screen"),pt(!0)});s("close-nfts").addEventListener("click",()=>{ae+=1,h&&V(h)});s("refresh-nfts").addEventListener("click",()=>{pt(!0)});s("close-nft-detail").addEventListener("click",()=>{Z=void 0,I("nfts-screen")});s("transfer-nft").addEventListener("click",()=>{U(async()=>{if(!Z)throw new Error("No NFT or RWA is selected.");nr(Z)})});s("nfts-previous").addEventListener("click",()=>{if(K<=1)return;K-=1;const e=++ae;Ce(),mt(e)});s("nfts-next").addEventListener("click",()=>{const e=Math.max(1,Math.ceil(J.length/ve));if(K>=e)return;K+=1;const t=++ae;Ce(),mt(t)});s("close-activity").addEventListener("click",()=>{h&&V(h)});s("close-transaction").addEventListener("click",()=>{en==="nft"&&Z?(xe(Z),I("nft-detail-screen")):I("activity-screen")});s("copy-transaction-txid").addEventListener("click",()=>{const e=_e==null?void 0:_e.txid;e&&navigator.clipboard.writeText(e).then(()=>{M.textContent="Transaction ID copied."}).catch(t=>{M.textContent=q(t)})});s("refresh-activity").addEventListener("click",()=>{fn()});s("refresh-balances").addEventListener("click",()=>{Be()});document.querySelectorAll("[data-token-filter]").forEach(e=>{e.addEventListener("click",()=>{Te=e.dataset.tokenFilter==="all"?"all":"held",document.querySelectorAll("[data-token-filter]").forEach(t=>{t.classList.toggle("active",t===e)}),st()})});s("close-receive").addEventListener("click",()=>{h&&V(h)});s("copy-receive-address").addEventListener("click",()=>{var t;const e=(t=s("receive-address-value").textContent)==null?void 0:t.trim();if(!e){M.textContent="No active wallet address is available.";return}navigator.clipboard.writeText(e).then(()=>{M.textContent="Wallet address copied."}).catch(n=>{M.textContent=q(n)})});s("save-wallet-settings").addEventListener("click",()=>{U(async()=>{const e=s("settings-api-url").value.replace(/\/+$/,""),t=new URL(e);if(t.protocol!=="https:"&&t.hostname!=="localhost"&&t.hostname!=="127.0.0.1")throw new Error("Contractless API URLs must use HTTPS.");const n=`${t.origin}/*`;if(!await chrome.permissions.contains({origins:[n]})&&!await chrome.permissions.request({origins:[n]}))throw new Error("Permission to contact this API endpoint was denied.");h=await $("save-settings",{apiUrl:e,autoLockMinutes:s("settings-lock-timeout").value}),M.textContent="Settings saved."})});document.querySelectorAll("[data-backup-action]").forEach(e=>{e.addEventListener("click",()=>{dt=e.dataset.backupAction,Ee(!0)})});s("close-backup-key").addEventListener("click",()=>Ee(!1));s("backup-key-backdrop").addEventListener("click",()=>Ee(!1));s("confirm-backup-key").addEventListener("click",()=>{const e=dt,t=s("backup-key-input").value;if(e){if(!t){M.textContent="Enter the active wallet encryption key.";return}U(async()=>{var r;if(e==="image"){const i=String(await $("export-private-key-image",{password:t,imagePassword:t})),a=((r=h==null?void 0:h.address)==null?void 0:r.split(".")[0])??"contractless";mn(i,`${a}.wallet.png`),Ee(!1),M.textContent="Wallet image downloaded.";return}const n=await $("reveal-private-key",{password:t});if(Ee(!1),e==="private"){s("revealed-private-key").value=n.privateKey,s("private-key-result").hidden=!1,s("private-key-result").scrollIntoView({block:"nearest"});return}const o=crypto.randomUUID();await chrome.storage.session.set({[`print-backup:${o}`]:{label:n.label,address:n.address,privateKey:n.privateKey,encryptionKey:t}}),await chrome.windows.create({url:chrome.runtime.getURL(`print.html?id=${encodeURIComponent(o)}`),type:"popup",width:820,height:760})})}});s("clear-private-key").addEventListener("click",gt);s("copy-private-key").addEventListener("click",()=>{const e=s("revealed-private-key").value;e&&navigator.clipboard.writeText(e).then(()=>{M.textContent="Private key copied."}).catch(t=>{M.textContent=q(t)})});document.querySelectorAll(".reveal").forEach(e=>{e.addEventListener("click",()=>{const t=s(String(e.dataset.input)),n=t.type==="text";t.type=n?"password":"text",e.textContent=n?"Show":"Hide"})});s("continue-create").addEventListener("click",()=>{try{Ne=Q(s("new-password").value,"Enter an encryption key."),s("verify-password").value="",I("verify-screen")}catch(e){M.textContent=q(e)}});s("create-wallet").addEventListener("click",()=>{if(s("verify-password").value!==Ne){M.textContent="The encryption keys do not match.";return}U(async()=>{const t=Ne,n=await $("create-wallet",{password:t});Ne="",s("new-password").value="",s("verify-password").value="",await pn(n,t)},!0).catch(()=>I("verify-screen",!1))});const ct=s("wallet-image");ct.addEventListener("change",()=>{var t;const e=(t=ct.files)==null?void 0:t[0];ge="",s("image-file-name").textContent=(e==null?void 0:e.name)??"Choose wallet image",e&&e.arrayBuffer().then(n=>{ge=cr(new Uint8Array(n))}).catch(n=>{M.textContent=q(n)})});s("import-image").addEventListener("click",()=>{const e=s("image-password").value;try{Q(e,"Enter the wallet image encryption key."),Q(ge,"Choose a wallet image.")}catch(t){M.textContent=q(t);return}U(async()=>{const t=await $("import-wallet-image",{imageBase64:ge,imagePassword:e,password:e});fe=e,ge="",ct.value="",s("image-password").value="",V(t)},!0).catch(()=>I("image-screen",!1))});s("import-private").addEventListener("click",()=>{const e=s("private-key").value.trim(),t=s("private-password").value;try{Q(e,"Paste the private key."),Q(t,"Enter a new encryption key.")}catch(n){M.textContent=q(n);return}U(async()=>{const n=await $("import-private-key",{privateKey:e,password:t});s("private-key").value="",s("private-password").value="",await pn(n,t)},!0).catch(()=>I("private-screen",!1))});s("save-image").addEventListener("click",()=>{U(async()=>{var n;if(!ie)throw new Error("The wallet image is not ready.");const e=((n=h==null?void 0:h.address)==null?void 0:n.split(".")[0])??"contractless";mn(ie,`${e}.wallet.png`);const t=s("backup-confirmed");t.disabled=!1,t.checked=!1,s("open-wallet").disabled=!0})});s("backup-confirmed").addEventListener("change",e=>{s("open-wallet").disabled=!e.currentTarget.checked});s("open-wallet").addEventListener("click",()=>{fe="",ie="",s("wallet-image-preview").removeAttribute("src"),h&&V(h)});s("unlock-form").addEventListener("submit",e=>{e.preventDefault();const t=s("unlock-password").value;try{Q(t,"Enter your encryption key.")}catch(n){M.textContent=q(n);return}U(async()=>{const n=await $("unlock",{password:t});fe=t,s("unlock-password").value="",V(n)},!0).catch(()=>I("locked-screen",!1))});s("approve-provider-approval").addEventListener("click",()=>{oe&&(ye("approve"),U(async()=>{const e=await $("resolve-provider-approval",{id:oe,approved:!0});oe="",await tn(e.remaining??0,!0)}).catch(()=>ye(null)))});s("reject-provider-approval").addEventListener("click",()=>{oe&&(ye("reject"),U(async()=>{const e=await $("resolve-provider-approval",{id:oe,approved:!1});oe="",await tn(e.remaining??0,!1)}).catch(()=>ye(null)))});$("status").then(e=>V(e)).catch(e=>{I("create-screen"),M.textContent=q(e)}); diff --git a/extension/dist/print.html b/extension/dist/print.html deleted file mode 100644 index 7eeccfa..0000000 --- a/extension/dist/print.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - Contractless Wallet Backup - - - - - -
- -
-

Contractless Wallet Backup

-

Private recovery information

-
-
- -

- Keep this page private. Anyone with the private key and encryption key can - control this wallet. -

- -
-

Wallet

-

-    
-
-

Address

-

-    
-
-

Private Key

-

-    
-
-

Encryption Key

-

-    
- - - - diff --git a/extension/dist/print.js b/extension/dist/print.js deleted file mode 100644 index c86b6e5..0000000 --- a/extension/dist/print.js +++ /dev/null @@ -1 +0,0 @@ -import"./chunks/modulepreload-polyfill-B5Qt9EMX.js";async function a(){const e=new URLSearchParams(location.search).get("id");if(!e)throw new Error("Missing printable wallet backup.");const n=`print-backup:${e}`,o=await chrome.storage.session.get(n);await chrome.storage.session.remove(n);const t=o[n];if(!t)throw new Error("The printable wallet backup has expired.");document.getElementById("wallet-label").textContent=t.label,document.getElementById("wallet-address").textContent=t.address,document.getElementById("wallet-private-key").textContent=t.privateKey,document.getElementById("wallet-encryption-key").textContent=t.encryptionKey,setTimeout(()=>{window.focus(),window.print()},150)}a().catch(e=>{document.getElementById("print-error").textContent=e instanceof Error?e.message:String(e)}); diff --git a/extension/dist/provider.js b/extension/dist/provider.js deleted file mode 100644 index 47444f0..0000000 --- a/extension/dist/provider.js +++ /dev/null @@ -1 +0,0 @@ -const a=new Map;window.addEventListener("message",e=>{var s,t,o;if(e.source!==window||((s=e.data)==null?void 0:s.source)!=="contractless-wallet")return;const r=a.get(e.data.id);r&&(a.delete(e.data.id),(t=e.data.response)!=null&&t.ok?r.resolve(e.data.response.result):r.reject(new Error(((o=e.data.response)==null?void 0:o.error)??"Wallet request failed.")))});const n=Object.freeze({isContractless:!0,request({method:e,params:r}){const s=crypto.randomUUID();return new Promise((t,o)=>{a.set(s,{resolve:t,reject:o}),window.postMessage({source:"contractless-page",id:s,method:e,params:r},window.location.origin)})}});Object.defineProperty(window,"contractless",{value:n,writable:!1,configurable:!1}); diff --git a/extension/src/manifest.chrome.json b/extension/src/manifest.chrome.json index c42233e..c9aa099 100644 --- a/extension/src/manifest.chrome.json +++ b/extension/src/manifest.chrome.json @@ -6,7 +6,7 @@ "content_security_policy": { "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'" }, - "permissions": ["storage", "alarms", "activeTab", "clipboardWrite"], + "permissions": ["storage", "alarms", "clipboardWrite"], "host_permissions": ["https://api.contractless.dev/*"], "optional_host_permissions": ["https://*/"], "action": { diff --git a/extension/src/manifest.firefox.json b/extension/src/manifest.firefox.json index 389d071..d2357e1 100644 --- a/extension/src/manifest.firefox.json +++ b/extension/src/manifest.firefox.json @@ -18,7 +18,7 @@ "content_security_policy": { "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'" }, - "permissions": ["storage", "alarms", "activeTab", "clipboardWrite"], + "permissions": ["storage", "alarms", "clipboardWrite"], "host_permissions": ["https://api.contractless.dev/*"], "optional_host_permissions": ["https://*/"], "action": { diff --git a/extension/src/popup.ts b/extension/src/popup.ts index 4d82910..c7523ca 100644 --- a/extension/src/popup.ts +++ b/extension/src/popup.ts @@ -120,6 +120,8 @@ let pendingTransfer: let lastSentTxid = ""; let pendingProviderApprovalId = ""; const CONFIRMED_AFTER_BLOCKS = 20; +const BALANCE_REFRESH_INTERVAL_MS = 15_000; +let balanceLoadInFlight = false; const TRANSACTION_NAMES: Record = { 1: "Mining Reward", @@ -532,12 +534,26 @@ function renderTokenBalances(): void { }); } -async function loadWalletBalances(): Promise { - if (!walletStatus?.unlocked) return; - walletBalances = undefined; - byId("base-balance").textContent = "--"; - byId("base-asset-balance").textContent = "--"; - renderTokenBalances(); +async function loadWalletBalances( + options: { showLoading?: boolean; reportErrors?: boolean } = {} +): Promise { + if (!walletStatus?.unlocked || balanceLoadInFlight) return; + + const requestedAddress = walletStatus.address; + const requestedNetwork = walletStatus.selectedNetwork; + const requestedApiUrl = walletStatus.apiUrl; + const hadBalances = walletBalances !== undefined; + const showLoading = options.showLoading ?? !hadBalances; + const reportErrors = options.reportErrors ?? true; + + balanceLoadInFlight = true; + if (showLoading) { + walletBalances = undefined; + byId("base-balance").textContent = "--"; + byId("base-asset-balance").textContent = "--"; + renderTokenBalances(); + } + try { if (!walletStatus.apiUrl) { throw new Error(`No ${walletStatus.networkName} API is configured.`); @@ -555,6 +571,16 @@ async function loadWalletBalances(): Promise { tokenCatalogError?: string; nftCatalogError?: string; }; + + if ( + !walletStatus?.unlocked + || walletStatus.address !== requestedAddress + || walletStatus.selectedNetwork !== requestedNetwork + || walletStatus.apiUrl !== requestedApiUrl + ) { + return; + } + walletBalances = { balances: Array.isArray(result.balances) ? result.balances : [], tokens: Array.isArray(result.tokens) ? result.tokens : [], @@ -572,20 +598,35 @@ async function loadWalletBalances(): Promise { byId("base-asset-balance").textContent = baseBalance; renderTokenBalances(); } catch (error) { - const list = byId("token-list"); - list.replaceChildren(); - const empty = document.createElement("div"); - empty.className = "empty-assets balance-error"; - const title = document.createElement("strong"); - title.textContent = "Unable to load balances"; - const description = document.createElement("span"); - description.textContent = errorText(error); - empty.append(title, description); - list.append(empty); - notice.textContent = errorText(error); + if (!hadBalances) { + const list = byId("token-list"); + list.replaceChildren(); + const empty = document.createElement("div"); + empty.className = "empty-assets balance-error"; + const title = document.createElement("strong"); + title.textContent = "Unable to load balances"; + const description = document.createElement("span"); + description.textContent = errorText(error); + empty.append(title, description); + list.append(empty); + } + if (reportErrors) notice.textContent = errorText(error); + } finally { + balanceLoadInFlight = false; } } +function refreshVisibleDashboard(): void { + if ( + document.hidden + || byId("dashboard-screen").hidden + || !walletStatus?.unlocked + ) { + return; + } + void loadWalletBalances({ showLoading: false, reportErrors: false }); +} + function nftKey(name: string, series: number): string { return `${name.trim().toUpperCase()}|${series}`; } @@ -2285,6 +2326,9 @@ byId("reject-provider-approval").addEventListener("click", () => { }).catch(() => setApprovalProcessing(null)); }); +window.setInterval(refreshVisibleDashboard, BALANCE_REFRESH_INTERVAL_MS); +document.addEventListener("visibilitychange", refreshVisibleDashboard); + send("status") .then((status) => showStatus(status as WalletStatus)) .catch((error) => { diff --git a/extension/src/wallet.css b/extension/src/wallet.css index f267e41..dcf6862 100644 --- a/extension/src/wallet.css +++ b/extension/src/wallet.css @@ -51,6 +51,32 @@ button:disabled { cursor: not-allowed; } .screen[hidden] { display: none; } +#create-screen, +#image-screen, +#private-screen, +#verify-screen, +#backup-screen { + overflow-x: hidden; + overflow-y: scroll; +} + +#create-screen::-webkit-scrollbar, +#image-screen::-webkit-scrollbar, +#private-screen::-webkit-scrollbar, +#verify-screen::-webkit-scrollbar, +#backup-screen::-webkit-scrollbar { + width: 8px; +} + +#create-screen::-webkit-scrollbar-thumb, +#image-screen::-webkit-scrollbar-thumb, +#private-screen::-webkit-scrollbar-thumb, +#verify-screen::-webkit-scrollbar-thumb, +#backup-screen::-webkit-scrollbar-thumb { + border: 2px solid var(--blue); + background: rgb(255 255 255 / 65%); +} + .wallet-header { height: 72px; display: flex;