From 30e26462db90bc341b02ecd5ce8ee1d94bae6565 Mon Sep 17 00:00:00 2001 From: Miguel Vieira Date: Tue, 9 May 2023 11:33:17 +0200 Subject: [PATCH 1/6] Feat/icp staking --- package-lock.json | 810 +++++++++++++----- package.json | 39 +- src/app/app-routing.module.ts | 4 +- .../account-edit-popover.component.ts | 5 +- src/app/components/components.module.ts | 3 + .../portfolio-item/portfolio-item.ts | 9 +- .../widget-input-delay.html | 31 + .../widget-input-delay.scss | 17 + .../widget-input-delay/widget-input-delay.ts | 48 ++ .../widget-selector/widget-selector.html | 1 + .../delegation/CoreumDelegationExtensions.ts | 30 +- .../delegation/CosmosDelegationExtensions.ts | 3 +- .../delegation/ICPDelegationExtensions.ts | 797 +++++++++++++++++ .../MoonbeamDelegationExtensions.ts | 5 +- .../SubstrateDelegationExtensions.ts | 1 + .../delegation/TezosDelegationExtensions.ts | 1 + .../base/ProtocolDelegationExtensions.ts | 11 +- .../base/V0ProtocolDelegationExtensions.ts | 18 +- .../base/V1ProtocolDelegationExtensions.ts | 40 +- .../interfaces/IAirGapCoinDelegateProtocol.ts | 13 +- src/app/models/ActionGroup.ts | 10 +- src/app/models/widgets/UIInputWidget.ts | 2 +- src/app/models/widgets/UIWidget.ts | 1 + src/app/models/widgets/input/UIInputDelay.ts | 67 ++ .../account-transaction-list.ts | 6 +- .../delegation-detail/delegation-detail.html | 334 ++++---- .../delegation-detail/delegation-detail.ts | 218 +++-- .../delegation-list/delegation-list.page.ts | 1 + .../transaction-confirm.ts | 47 +- .../services/extensions/extensions.service.ts | 42 +- src/app/services/operations/operations.ts | 91 +- src/assets/i18n/en.json | 53 ++ 32 files changed, 2234 insertions(+), 524 deletions(-) create mode 100644 src/app/components/widget-input-delay/widget-input-delay.html create mode 100644 src/app/components/widget-input-delay/widget-input-delay.scss create mode 100644 src/app/components/widget-input-delay/widget-input-delay.ts create mode 100644 src/app/extensions/delegation/ICPDelegationExtensions.ts create mode 100644 src/app/models/widgets/input/UIInputDelay.ts diff --git a/package-lock.json b/package-lock.json index 7c2a7931e..dc224386e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,27 +9,27 @@ "version": "0.0.1", "hasInstallScript": true, "dependencies": { - "@airgap/aeternity": "0.13.14", - "@airgap/angular-core": "0.0.36", - "@airgap/angular-ngrx": "0.0.36", - "@airgap/astar": "0.13.14", + "@airgap/aeternity": "0.13.15-beta.10", + "@airgap/angular-core": "0.0.37-beta.17", + "@airgap/angular-ngrx": "0.0.37-beta.17", + "@airgap/astar": "0.13.15-beta.10", "@airgap/beacon-sdk": "3.1.5-beta.0", - "@airgap/bitcoin": "0.13.14", - "@airgap/coinlib-core": "0.13.14", - "@airgap/coreum": "0.13.14", - "@airgap/cosmos": "0.13.14", - "@airgap/cosmos-core": "0.13.14", - "@airgap/crypto": "0.13.14", - "@airgap/ethereum": "0.13.14", - "@airgap/groestlcoin": "0.13.14", - "@airgap/icp": "0.13.14", - "@airgap/module-kit": "0.13.14", - "@airgap/moonbeam": "0.13.14", - "@airgap/polkadot": "0.13.14", + "@airgap/bitcoin": "0.13.15-beta.10", + "@airgap/coinlib-core": "0.13.15-beta.10", + "@airgap/coreum": "0.13.15-beta.10", + "@airgap/cosmos": "0.13.15-beta.10", + "@airgap/cosmos-core": "0.13.15-beta.10", + "@airgap/crypto": "0.13.15-beta.10", + "@airgap/ethereum": "0.13.15-beta.10", + "@airgap/groestlcoin": "0.13.15-beta.10", + "@airgap/icp": "0.13.15-beta.10", + "@airgap/module-kit": "0.13.15-beta.10", + "@airgap/moonbeam": "0.13.15-beta.10", + "@airgap/polkadot": "0.13.15-beta.10", "@airgap/sapling-wasm": "0.0.7", - "@airgap/serializer": "0.13.14", - "@airgap/substrate": "0.13.14", - "@airgap/tezos": "0.13.14", + "@airgap/serializer": "0.13.15-beta.10", + "@airgap/substrate": "0.13.15-beta.10", + "@airgap/tezos": "0.13.15-beta.10", "@angular/animations": "^11.2.9", "@angular/common": "^11.2.9", "@angular/core": "^11.2.9", @@ -101,6 +101,7 @@ "graphql": "^16.0.1", "graphql-request": "^3.6.1", "html-loader": "^2.1.2", + "humanize-duration": "^3.28.0", "ionicons": "^5.5.1", "localforage-cordovasqlitedriver": "^1.7.0", "moment": "^2.29.1", @@ -161,9 +162,9 @@ } }, "node_modules/@airgap/aeternity": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/aeternity/-/aeternity-0.13.14.tgz", - "integrity": "sha512-n8FI49ZDXDMQTROy0+f4GGaMLelaIJ9Kg2+KAiB4Uin+QCxtUICmMT1IIKM8rFg2NmuWBtfoaomuTbdtUrJwYw==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/aeternity/-/aeternity-0.13.15-beta.10.tgz", + "integrity": "sha512-Yi19sQMqQwZJ20fCbPUfpkLDBZLu7RangN8bePQotPaV45rZt45FplxNC+iCRdbAGbSUdWPhTeLzn+USXoA8TA==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -172,30 +173,30 @@ } }, "node_modules/@airgap/angular-core": { - "version": "0.0.36", - "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.36.tgz", - "integrity": "sha512-iMf8MKB5OTfh+PRZXLY07y8xD4eSvdU9CeWmpSb+eu0utr6sXTOo4vbQNTDfO6PCGyfXcdXOL8ddxsyUSnGz+g==", + "version": "0.0.37-beta.17", + "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.37-beta.17.tgz", + "integrity": "sha512-7Sadka8upZcZTnDUGzVo+08sQanPTMZGfQXhm8uF3x8+89OGQcfXx0k8q8EBV+eMCyivOg8EjlfwVEQjvYSpTw==", "dependencies": { "tslib": "^2.2.0" }, "peerDependencies": { - "@airgap/aeternity": "^0.13.12", - "@airgap/astar": "^0.13.12", - "@airgap/bitcoin": "^0.13.12", - "@airgap/coinlib-core": "^0.13.12", - "@airgap/coreum": "^0.13.12", - "@airgap/cosmos": "^0.13.12", - "@airgap/cosmos-core": "^0.13.12", - "@airgap/crypto": "^0.13.12", - "@airgap/ethereum": "^0.13.12", - "@airgap/groestlcoin": "^0.13.12", - "@airgap/icp": "^0.13.12", - "@airgap/module-kit": "^0.13.12", - "@airgap/moonbeam": "^0.13.12", - "@airgap/polkadot": "^0.13.12", - "@airgap/serializer": "^0.13.12", - "@airgap/substrate": "^0.13.12", - "@airgap/tezos": "^0.13.12", + "@airgap/aeternity": "^0.13.15-beta.10", + "@airgap/astar": "^0.13.15-beta.10", + "@airgap/bitcoin": "^0.13.15-beta.10", + "@airgap/coinlib-core": "^0.13.15-beta.10", + "@airgap/coreum": "^0.13.15-beta.10", + "@airgap/cosmos": "^0.13.15-beta.10", + "@airgap/cosmos-core": "^0.13.15-beta.10", + "@airgap/crypto": "^0.13.15-beta.10", + "@airgap/ethereum": "^0.13.15-beta.10", + "@airgap/groestlcoin": "^0.13.15-beta.10", + "@airgap/icp": "^0.13.15-beta.10", + "@airgap/module-kit": "^0.13.15-beta.10", + "@airgap/moonbeam": "^0.13.15-beta.10", + "@airgap/polkadot": "^0.13.15-beta.10", + "@airgap/serializer": "^0.13.15-beta.10", + "@airgap/substrate": "^0.13.15-beta.10", + "@airgap/tezos": "^0.13.15-beta.10", "@angular/animations": "^11.2.9", "@angular/common": "^11.2.9", "@angular/core": "^11.2.9", @@ -236,15 +237,15 @@ } }, "node_modules/@airgap/angular-ngrx": { - "version": "0.0.36", - "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.36.tgz", - "integrity": "sha512-qYa2NUXmsfiAxDxij7inBgyKwv/Gwa/pzBJAXcypdLwt0PSnaHoQpllSTc/jcDJaYKW+sp8xVW46fUilJ9oGMQ==", + "version": "0.0.37-beta.17", + "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.37-beta.17.tgz", + "integrity": "sha512-swQ55n5qJ0r4i6IirciGg4YfBa/75vbTlyRMTO01cSgvBBSD4PWjyg5bhyr1WkQRwc80rh1PG7d0pljXm4L8+w==", "dependencies": { "tslib": "^2.2.0" }, "peerDependencies": { "@airgap/angular-core": "^0.0.36", - "@airgap/coinlib-core": "^0.13.12", + "@airgap/coinlib-core": "^0.13.15-beta.10", "@angular/common": "^11.2.9", "@angular/core": "^11.2.9", "@angular/platform-browser": "^11.2.9", @@ -258,9 +259,9 @@ } }, "node_modules/@airgap/astar": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/astar/-/astar-0.13.14.tgz", - "integrity": "sha512-2aUxduCMsyuY/HUYjcYy/GZWHBP+92IHFA2rBYCeuiWJlSEG8hUbSdsI0dE4RDab+AV4UjkkI0GDe7BCbI+6PA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/astar/-/astar-0.13.15-beta.10.tgz", + "integrity": "sha512-Sn/3Gaun9m5JqMpmiNx9fKXsdOTuzShkoYmtEV7Y00OdmExHQR3Dojfy2M/DJ1kjjVj4gT5COELFk/T/+tsp2g==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -409,9 +410,9 @@ } }, "node_modules/@airgap/bitcoin": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/bitcoin/-/bitcoin-0.13.14.tgz", - "integrity": "sha512-iRHlvrAaCamoGZQzQe+z2b8+vB/JYJIN3AuzeEoT3KlaQSz2tuWH0JHB8me57ykpecu+rvowl95cYymVjr7AIQ==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/bitcoin/-/bitcoin-0.13.15-beta.10.tgz", + "integrity": "sha512-G/vStubCH9DtSIqQ3Mh/loUBSMrfL+s+SJPPLIWUb4YKqXNS272jE1XqW6MTsfv9BTt40P9ZD1Nw8NLYwDvgQQ==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -421,9 +422,9 @@ } }, "node_modules/@airgap/coinlib-core": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/coinlib-core/-/coinlib-core-0.13.14.tgz", - "integrity": "sha512-hqx2zeyVEHRRU0ziERIlUCl8b0LOQJbam3pOzjsxhKggNKoZ1TBZwSNMBdysVpRVbfJ6SVLYs3OeesVFDBVD3A==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/coinlib-core/-/coinlib-core-0.13.15-beta.10.tgz", + "integrity": "sha512-icwj44ScCimoBHZR8DBdOFg2bzlab8nk8K2DGlMfCPhMO8xq+huA9RFp9qqOGo4++sGc+kQDJGihyTugSmw0Lg==", "dependencies": { "@stablelib/blake2b": "^1.0.1", "@stablelib/bytes": "^1.0.1", @@ -435,9 +436,9 @@ } }, "node_modules/@airgap/coreum": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/coreum/-/coreum-0.13.14.tgz", - "integrity": "sha512-1eZErv6fVa1dHyWlLck/Z8atCaUVEyGkd/ZAUMNUfXBj0mhd+zEfWUR6TFs5d++3djHNXE1M5niRX9N14ZorhA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/coreum/-/coreum-0.13.15-beta.10.tgz", + "integrity": "sha512-BL8nCoEDU+ysJSF7rFX3CWNE0JQcBK3iIYsV7ZTayZ2/fMBP0E/rAoUoFye/nh7BRP0USj050jI9nyzJVqcG2Q==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/cosmos-core": "*", @@ -447,9 +448,9 @@ } }, "node_modules/@airgap/cosmos": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/cosmos/-/cosmos-0.13.14.tgz", - "integrity": "sha512-OMzNpkIIiPE2UnDuR04icZKjdsj4R4libKUFfDKkCqTCv7g8+5jMksnT8v/DF3f6IztVN4/fO5b0yidERiRzMA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/cosmos/-/cosmos-0.13.15-beta.10.tgz", + "integrity": "sha512-TA4OaMh08jgDuUgOggB2cUqvUOCRK5uoNYf2VCsFtgCucGUkIQ3BeDi7n7PhxpF9cdcMb/S/PDkEh/mz3dtX5g==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/cosmos-core": "*", @@ -459,9 +460,9 @@ } }, "node_modules/@airgap/cosmos-core": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/cosmos-core/-/cosmos-core-0.13.14.tgz", - "integrity": "sha512-soogELNbMMNKlCYnscDzgUcJCBRqHbfIt7aYGBf6wJgXXsL2WieeVSaripWTX72QvuqOM0UtjF5ZxQQn9dRUnw==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/cosmos-core/-/cosmos-core-0.13.15-beta.10.tgz", + "integrity": "sha512-jID1O5Tpuydrt6wibsM1ergRHDUQ1GdSEcHHc9W7B6EZZL+9HS0j1Ehx+8naMwqrNkvqaM4wOCVI9hr2bX9b8g==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -470,9 +471,9 @@ } }, "node_modules/@airgap/crypto": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/crypto/-/crypto-0.13.14.tgz", - "integrity": "sha512-S/IBbRXQ7zFOSU8uuTcaV2gHe1JTk93Ryx9pYAMEV/+Jn2OTbSfGZyMV7B9ufR5qtljD1El/sBDkcpmEERmVwA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/crypto/-/crypto-0.13.15-beta.10.tgz", + "integrity": "sha512-PU8+3UGxYfpToAgodUAiex7zfLAdcAz+WMgxFYGcJQ/E9pOJq7t8Nc12b3dOAlIpoGtj3iqlN0AR7rf/BfG50A==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -487,9 +488,9 @@ "integrity": "sha512-rJjV7JIDxoardnZMgk4Uor5Z6OVsAE4I5uDlkGAb0tQ5NN0gmz9Bu2LKMPSCv7UqDpZowDX4BbMDuSqdO/IsbQ==" }, "node_modules/@airgap/ethereum": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/ethereum/-/ethereum-0.13.14.tgz", - "integrity": "sha512-yAk0pV+wrDbVfZDkg8WxYsv6qJ2qGlA6WPNAJn5CpPPBxyqONCt+PauRXYJL0A4yKTUYxSEiVLbhdiEs3BON2A==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/ethereum/-/ethereum-0.13.15-beta.10.tgz", + "integrity": "sha512-zDZVrI53bzXCP5LOk7dojrxXkqcNFxHd0gCGiwiMKJb2h45qf27FLZMuCI8WzyfPtAo1tZhxzVqCAWt8hRYUCg==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -501,9 +502,9 @@ } }, "node_modules/@airgap/groestlcoin": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/groestlcoin/-/groestlcoin-0.13.14.tgz", - "integrity": "sha512-7iVg3SL6S2OAE5aCoTAXnltE2BbTBxgk1cani63SqHzpkODXw/nrmHJSVCWZYW0raOYX42jXous5GkgFjUyVOg==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/groestlcoin/-/groestlcoin-0.13.15-beta.10.tgz", + "integrity": "sha512-uTzPud+ti2SCHmGzxU57dmpC5Msn+pDffDf++Xt05XSUMmCqDVAW/7RuJHoFxPxdYq7WFBmw+Slard5/1qPIiw==", "dependencies": { "@airgap/bitcoin": "*", "@airgap/coinlib-core": "*", @@ -512,19 +513,21 @@ } }, "node_modules/@airgap/icp": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/icp/-/icp-0.13.14.tgz", - "integrity": "sha512-U4ZnHSwMdzYw4c989wooochUzeHINGL9Rcgj+vQTVp6FjSmwWndqTZuaPREUoUBvpkRKD03bu//HF40bjcs7zg==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/icp/-/icp-0.13.15-beta.10.tgz", + "integrity": "sha512-rB9u5YuTKrUzVrmE9wcgbDkyFJwric2hlEiENy42fYbj64IB++GCkjyUiC5kXLKl5sjQkOBIW7z7mT7B02avBg==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", "@airgap/module-kit": "*", "@airgap/serializer": "*", + "@dfinity/agent": "^0.15.4", + "@dfinity/identity-secp256k1": "^0.15.4", + "@dfinity/nns": "^0.14.0", "@stablelib/ed25519": "^1.0.3", "base64-arraybuffer": "^1.0.2", "bip39": "^3.0.4", "borc": "^3.0.0", - "crc": "4.3.2", "crc-32": "1.2.2", "isomorphic-fetch": "^3.0.0", "js-sha256": "^0.9.0", @@ -556,22 +559,6 @@ "randombytes": "^2.0.1" } }, - "node_modules/@airgap/icp/node_modules/crc": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/crc/-/crc-4.3.2.tgz", - "integrity": "sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A==", - "engines": { - "node": ">=12" - }, - "peerDependencies": { - "buffer": ">=6.0.3" - }, - "peerDependenciesMeta": { - "buffer": { - "optional": true - } - } - }, "node_modules/@airgap/icp/node_modules/node-addon-api": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", @@ -592,18 +579,18 @@ } }, "node_modules/@airgap/module-kit": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/module-kit/-/module-kit-0.13.14.tgz", - "integrity": "sha512-tZIOQoDZrgdOqnVICGjIJABXZAyuf5TqlZ0aNpBjUOVpoWnrBNWhVUhm9nj/CSZKFxBlWXhTbi68TF/zFKQe5w==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/module-kit/-/module-kit-0.13.15-beta.10.tgz", + "integrity": "sha512-nYJkKvf8+tS6Q2Lt7THnEDtBtg1omKwuzEcHtavShWyugTqhmmMcGBKVwrMOI0gNdxfC4ap+BxFDCdrOZXq/ZA==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/serializer": "*" } }, "node_modules/@airgap/moonbeam": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/moonbeam/-/moonbeam-0.13.14.tgz", - "integrity": "sha512-uB/sKRsgfas7zdbLKQ4CYpkuf0+gXjSqkALQga9xvR+ZOuzAkpR1wR98QXKpay53zye5BBj8+bOBK7oiOc/j1w==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/moonbeam/-/moonbeam-0.13.15-beta.10.tgz", + "integrity": "sha512-CahZ8Gv+m684KBcjJrHyXdCWsVbFvZUXRcNnIYyR3Iey2OpxTiWZWPKl8FVsq4zl/UeXPB3iZGfOkf/5E5/D0g==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -612,9 +599,9 @@ } }, "node_modules/@airgap/polkadot": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/polkadot/-/polkadot-0.13.14.tgz", - "integrity": "sha512-05r0cuY4zm45Ax7xWlRRQNWTLIAKSR4z+ho+DWOY2KQA6iQpu6NwuG6XCasXEeaCzqcs/glgJ3aMWihyvI7IeA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/polkadot/-/polkadot-0.13.15-beta.10.tgz", + "integrity": "sha512-lqDlSx1GfyA9Xsi1UrDfcJkFuWuDeiNqTS6HLokCfR+PO/g3HawKEg3bINtLnv2uAKvclKx8iylbDq+oxZamxA==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -627,17 +614,17 @@ "integrity": "sha512-IMODbGPTBYKuO5ztiHX9C1PTlhqZvmVWv7m7zj5+VMcbBxrk4+jBAf7FYTH5l+IUsNMaHBOuh8Qq3A1b/pm7jQ==" }, "node_modules/@airgap/serializer": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/serializer/-/serializer-0.13.14.tgz", - "integrity": "sha512-VJFug2/BABrORd0AuPTB/3QEv4LBt8EQvbQAg9dvt/+HpVooWtZGw4DrFqcqYvMAo3DA77OQ7R55UzGvTBLrDA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/serializer/-/serializer-0.13.15-beta.10.tgz", + "integrity": "sha512-woa1UG/UJQxlLuAxWpxxbHdIyPDGzNiEbdmBMe7HGi0IMnT+4SRqhQcLGBUSoPG4zB2hy00U4eICNGGaJDqhLg==", "dependencies": { "@airgap/coinlib-core": "*" } }, "node_modules/@airgap/substrate": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/substrate/-/substrate-0.13.14.tgz", - "integrity": "sha512-VMlcq10OB68y9v81aUQ2LiY3Lk0NIjOPea0jHrAxf9DVu81oLgajHAt0x6g3TcPQDqQ8eRoHeyPAjFnbSNDu3w==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/substrate/-/substrate-0.13.15-beta.10.tgz", + "integrity": "sha512-f+qapP2tx3X4GzcqAZm3RJ7ctAUIOqFLugmzSEeiYTxYdoohfLyxpvMyh2ErpNoIRDQCzraQ8zZ0G9UUr5KTxg==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -648,9 +635,9 @@ } }, "node_modules/@airgap/tezos": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/tezos/-/tezos-0.13.14.tgz", - "integrity": "sha512-2HDHCMpvS4C6ZF2aqprGZPC+mPKqdH4ZgdCJiv+gSnExhzhtBJXNrqFzycGrrbVihZQnr/wUQ6B+3OIkEfhIhA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/tezos/-/tezos-0.13.15-beta.10.tgz", + "integrity": "sha512-mvcXr6SDaWOftWXv4IzFpKoDBJx++jH4suubxGqUrvgvJGDEVq5/Ynp6ce3m0nb9lL//T+IF73rmnqCCfkgmMA==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -3483,6 +3470,191 @@ "@capacitor/core": "^4.0.0" } }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@dfinity/agent": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-0.15.5.tgz", + "integrity": "sha512-Ytn8eo0Gk8QkaCX2X+CS1NYOdCr0ZjanqFyKbR5rY7LGQoVaNzdVHJufzheuTFMhTZs6i/OtaG2BQug4cNIocw==", + "dependencies": { + "base64-arraybuffer": "^0.2.0", + "bignumber.js": "^9.0.0", + "borc": "^2.1.1", + "js-sha256": "0.9.0", + "simple-cbor": "^0.4.1", + "ts-node": "^10.8.2" + }, + "peerDependencies": { + "@dfinity/candid": "^0.15.5", + "@dfinity/principal": "^0.15.5" + } + }, + "node_modules/@dfinity/agent/node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@dfinity/agent/node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@dfinity/agent/node_modules/base64-arraybuffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", + "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/@dfinity/agent/node_modules/borc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/borc/-/borc-2.1.2.tgz", + "integrity": "sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w==", + "dependencies": { + "bignumber.js": "^9.0.0", + "buffer": "^5.5.0", + "commander": "^2.15.0", + "ieee754": "^1.1.13", + "iso-url": "~0.4.7", + "json-text-sequence": "~0.1.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@dfinity/agent/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/@dfinity/agent/node_modules/iso-url": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz", + "integrity": "sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@dfinity/agent/node_modules/json-text-sequence": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/json-text-sequence/-/json-text-sequence-0.1.1.tgz", + "integrity": "sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w==", + "dependencies": { + "delimit-stream": "0.1.0" + } + }, + "node_modules/@dfinity/agent/node_modules/ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/@dfinity/identity-secp256k1": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/@dfinity/identity-secp256k1/-/identity-secp256k1-0.15.5.tgz", + "integrity": "sha512-W0Y1bpuC6Nkl3zZlsFhYpLlaF6yw6uCZOEbLPqNfdUB5jv1fOS8SSsl557L3cG5d9utDLJOA9ejZ8cWxcTEMSw==", + "dependencies": { + "@dfinity/agent": "^0.15.5", + "bip39": "^3.0.4", + "bs58check": "^2.1.2", + "secp256k1": "^4.0.3" + } + }, + "node_modules/@dfinity/identity-secp256k1/node_modules/bip39": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", + "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "dependencies": { + "@noble/hashes": "^1.2.0" + } + }, + "node_modules/@dfinity/nns": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@dfinity/nns/-/nns-0.14.0.tgz", + "integrity": "sha512-qQ3SzihD9hL2Zo0pAC+Ip2snbEtLDL1Aq2JTnDMLur9DEpiCajzhjXfsOy+U1zeSTOc+RUBbbWeLbS5Edsxeig==", + "dependencies": { + "crc": "^4.3.2", + "crc-32": "^1.2.2", + "google-protobuf": "^3.21.2", + "js-sha256": "^0.9.0", + "randombytes": "^2.1.0" + }, + "peerDependencies": { + "@dfinity/utils": "^0.0.12" + } + }, + "node_modules/@dfinity/nns/node_modules/crc": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/crc/-/crc-4.3.2.tgz", + "integrity": "sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A==", + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "buffer": ">=6.0.3" + }, + "peerDependenciesMeta": { + "buffer": { + "optional": true + } + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", @@ -4081,6 +4253,28 @@ "node": ">=8" } }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "node_modules/@jsdevtools/coverage-istanbul-loader": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz", @@ -4452,6 +4646,17 @@ "rxjs": ">=6.5.3" } }, + "node_modules/@noble/hashes": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", + "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5331,6 +5536,26 @@ "node": ">=10.13.0" } }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, "node_modules/@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", @@ -6517,8 +6742,7 @@ "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" }, "node_modules/argparse": { "version": "1.0.10", @@ -9240,8 +9464,7 @@ "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "node_modules/critters": { "version": "0.0.7", @@ -10331,6 +10554,11 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, + "node_modules/delimit-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", + "integrity": "sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ==" + }, "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -10418,7 +10646,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, "engines": { "node": ">=0.3.1" } @@ -12885,6 +13112,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" + }, "node_modules/got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -13633,6 +13865,11 @@ "node": ">=8.12.0" } }, + "node_modules/humanize-duration": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.28.0.tgz", + "integrity": "sha512-jMAxraOOmHuPbffLVDKkEKi/NeG8dMqP8lGRd6Tbf7JgAeG33jjgPWDbXXU7ypCI0o+oNKJFgbSB9FKVdWNI2A==" + }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -15945,8 +16182,7 @@ "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" }, "node_modules/make-fetch-happen": { "version": "8.0.14", @@ -24400,6 +24636,11 @@ "uuid": "bin/uuid" } }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -26248,7 +26489,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, "engines": { "node": ">=6" } @@ -26276,9 +26516,9 @@ }, "dependencies": { "@airgap/aeternity": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/aeternity/-/aeternity-0.13.14.tgz", - "integrity": "sha512-n8FI49ZDXDMQTROy0+f4GGaMLelaIJ9Kg2+KAiB4Uin+QCxtUICmMT1IIKM8rFg2NmuWBtfoaomuTbdtUrJwYw==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/aeternity/-/aeternity-0.13.15-beta.10.tgz", + "integrity": "sha512-Yi19sQMqQwZJ20fCbPUfpkLDBZLu7RangN8bePQotPaV45rZt45FplxNC+iCRdbAGbSUdWPhTeLzn+USXoA8TA==", "requires": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -26287,25 +26527,25 @@ } }, "@airgap/angular-core": { - "version": "0.0.36", - "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.36.tgz", - "integrity": "sha512-iMf8MKB5OTfh+PRZXLY07y8xD4eSvdU9CeWmpSb+eu0utr6sXTOo4vbQNTDfO6PCGyfXcdXOL8ddxsyUSnGz+g==", + "version": "0.0.37-beta.17", + "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.37-beta.17.tgz", + "integrity": "sha512-7Sadka8upZcZTnDUGzVo+08sQanPTMZGfQXhm8uF3x8+89OGQcfXx0k8q8EBV+eMCyivOg8EjlfwVEQjvYSpTw==", "requires": { "tslib": "^2.2.0" } }, "@airgap/angular-ngrx": { - "version": "0.0.36", - "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.36.tgz", - "integrity": "sha512-qYa2NUXmsfiAxDxij7inBgyKwv/Gwa/pzBJAXcypdLwt0PSnaHoQpllSTc/jcDJaYKW+sp8xVW46fUilJ9oGMQ==", + "version": "0.0.37-beta.17", + "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.37-beta.17.tgz", + "integrity": "sha512-swQ55n5qJ0r4i6IirciGg4YfBa/75vbTlyRMTO01cSgvBBSD4PWjyg5bhyr1WkQRwc80rh1PG7d0pljXm4L8+w==", "requires": { "tslib": "^2.2.0" } }, "@airgap/astar": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/astar/-/astar-0.13.14.tgz", - "integrity": "sha512-2aUxduCMsyuY/HUYjcYy/GZWHBP+92IHFA2rBYCeuiWJlSEG8hUbSdsI0dE4RDab+AV4UjkkI0GDe7BCbI+6PA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/astar/-/astar-0.13.15-beta.10.tgz", + "integrity": "sha512-Sn/3Gaun9m5JqMpmiNx9fKXsdOTuzShkoYmtEV7Y00OdmExHQR3Dojfy2M/DJ1kjjVj4gT5COELFk/T/+tsp2g==", "requires": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -26458,9 +26698,9 @@ } }, "@airgap/bitcoin": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/bitcoin/-/bitcoin-0.13.14.tgz", - "integrity": "sha512-iRHlvrAaCamoGZQzQe+z2b8+vB/JYJIN3AuzeEoT3KlaQSz2tuWH0JHB8me57ykpecu+rvowl95cYymVjr7AIQ==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/bitcoin/-/bitcoin-0.13.15-beta.10.tgz", + "integrity": "sha512-G/vStubCH9DtSIqQ3Mh/loUBSMrfL+s+SJPPLIWUb4YKqXNS272jE1XqW6MTsfv9BTt40P9ZD1Nw8NLYwDvgQQ==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -26470,9 +26710,9 @@ } }, "@airgap/coinlib-core": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/coinlib-core/-/coinlib-core-0.13.14.tgz", - "integrity": "sha512-hqx2zeyVEHRRU0ziERIlUCl8b0LOQJbam3pOzjsxhKggNKoZ1TBZwSNMBdysVpRVbfJ6SVLYs3OeesVFDBVD3A==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/coinlib-core/-/coinlib-core-0.13.15-beta.10.tgz", + "integrity": "sha512-icwj44ScCimoBHZR8DBdOFg2bzlab8nk8K2DGlMfCPhMO8xq+huA9RFp9qqOGo4++sGc+kQDJGihyTugSmw0Lg==", "requires": { "@stablelib/blake2b": "^1.0.1", "@stablelib/bytes": "^1.0.1", @@ -26484,9 +26724,9 @@ } }, "@airgap/coreum": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/coreum/-/coreum-0.13.14.tgz", - "integrity": "sha512-1eZErv6fVa1dHyWlLck/Z8atCaUVEyGkd/ZAUMNUfXBj0mhd+zEfWUR6TFs5d++3djHNXE1M5niRX9N14ZorhA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/coreum/-/coreum-0.13.15-beta.10.tgz", + "integrity": "sha512-BL8nCoEDU+ysJSF7rFX3CWNE0JQcBK3iIYsV7ZTayZ2/fMBP0E/rAoUoFye/nh7BRP0USj050jI9nyzJVqcG2Q==", "requires": { "@airgap/coinlib-core": "*", "@airgap/cosmos-core": "*", @@ -26496,9 +26736,9 @@ } }, "@airgap/cosmos": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/cosmos/-/cosmos-0.13.14.tgz", - "integrity": "sha512-OMzNpkIIiPE2UnDuR04icZKjdsj4R4libKUFfDKkCqTCv7g8+5jMksnT8v/DF3f6IztVN4/fO5b0yidERiRzMA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/cosmos/-/cosmos-0.13.15-beta.10.tgz", + "integrity": "sha512-TA4OaMh08jgDuUgOggB2cUqvUOCRK5uoNYf2VCsFtgCucGUkIQ3BeDi7n7PhxpF9cdcMb/S/PDkEh/mz3dtX5g==", "requires": { "@airgap/coinlib-core": "*", "@airgap/cosmos-core": "*", @@ -26508,9 +26748,9 @@ } }, "@airgap/cosmos-core": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/cosmos-core/-/cosmos-core-0.13.14.tgz", - "integrity": "sha512-soogELNbMMNKlCYnscDzgUcJCBRqHbfIt7aYGBf6wJgXXsL2WieeVSaripWTX72QvuqOM0UtjF5ZxQQn9dRUnw==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/cosmos-core/-/cosmos-core-0.13.15-beta.10.tgz", + "integrity": "sha512-jID1O5Tpuydrt6wibsM1ergRHDUQ1GdSEcHHc9W7B6EZZL+9HS0j1Ehx+8naMwqrNkvqaM4wOCVI9hr2bX9b8g==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -26519,9 +26759,9 @@ } }, "@airgap/crypto": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/crypto/-/crypto-0.13.14.tgz", - "integrity": "sha512-S/IBbRXQ7zFOSU8uuTcaV2gHe1JTk93Ryx9pYAMEV/+Jn2OTbSfGZyMV7B9ufR5qtljD1El/sBDkcpmEERmVwA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/crypto/-/crypto-0.13.15-beta.10.tgz", + "integrity": "sha512-PU8+3UGxYfpToAgodUAiex7zfLAdcAz+WMgxFYGcJQ/E9pOJq7t8Nc12b3dOAlIpoGtj3iqlN0AR7rf/BfG50A==", "requires": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -26538,9 +26778,9 @@ } }, "@airgap/ethereum": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/ethereum/-/ethereum-0.13.14.tgz", - "integrity": "sha512-yAk0pV+wrDbVfZDkg8WxYsv6qJ2qGlA6WPNAJn5CpPPBxyqONCt+PauRXYJL0A4yKTUYxSEiVLbhdiEs3BON2A==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/ethereum/-/ethereum-0.13.15-beta.10.tgz", + "integrity": "sha512-zDZVrI53bzXCP5LOk7dojrxXkqcNFxHd0gCGiwiMKJb2h45qf27FLZMuCI8WzyfPtAo1tZhxzVqCAWt8hRYUCg==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -26552,9 +26792,9 @@ } }, "@airgap/groestlcoin": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/groestlcoin/-/groestlcoin-0.13.14.tgz", - "integrity": "sha512-7iVg3SL6S2OAE5aCoTAXnltE2BbTBxgk1cani63SqHzpkODXw/nrmHJSVCWZYW0raOYX42jXous5GkgFjUyVOg==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/groestlcoin/-/groestlcoin-0.13.15-beta.10.tgz", + "integrity": "sha512-uTzPud+ti2SCHmGzxU57dmpC5Msn+pDffDf++Xt05XSUMmCqDVAW/7RuJHoFxPxdYq7WFBmw+Slard5/1qPIiw==", "requires": { "@airgap/bitcoin": "*", "@airgap/coinlib-core": "*", @@ -26563,19 +26803,21 @@ } }, "@airgap/icp": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/icp/-/icp-0.13.14.tgz", - "integrity": "sha512-U4ZnHSwMdzYw4c989wooochUzeHINGL9Rcgj+vQTVp6FjSmwWndqTZuaPREUoUBvpkRKD03bu//HF40bjcs7zg==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/icp/-/icp-0.13.15-beta.10.tgz", + "integrity": "sha512-rB9u5YuTKrUzVrmE9wcgbDkyFJwric2hlEiENy42fYbj64IB++GCkjyUiC5kXLKl5sjQkOBIW7z7mT7B02avBg==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", "@airgap/module-kit": "*", "@airgap/serializer": "*", + "@dfinity/agent": "^0.15.4", + "@dfinity/identity-secp256k1": "^0.15.4", + "@dfinity/nns": "^0.14.0", "@stablelib/ed25519": "^1.0.3", "base64-arraybuffer": "^1.0.2", "bip39": "^3.0.4", "borc": "^3.0.0", - "crc": "4.3.2", "crc-32": "1.2.2", "isomorphic-fetch": "^3.0.0", "js-sha256": "^0.9.0", @@ -26604,11 +26846,6 @@ "randombytes": "^2.0.1" } }, - "crc": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/crc/-/crc-4.3.2.tgz", - "integrity": "sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A==" - }, "node-addon-api": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", @@ -26627,18 +26864,18 @@ } }, "@airgap/module-kit": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/module-kit/-/module-kit-0.13.14.tgz", - "integrity": "sha512-tZIOQoDZrgdOqnVICGjIJABXZAyuf5TqlZ0aNpBjUOVpoWnrBNWhVUhm9nj/CSZKFxBlWXhTbi68TF/zFKQe5w==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/module-kit/-/module-kit-0.13.15-beta.10.tgz", + "integrity": "sha512-nYJkKvf8+tS6Q2Lt7THnEDtBtg1omKwuzEcHtavShWyugTqhmmMcGBKVwrMOI0gNdxfC4ap+BxFDCdrOZXq/ZA==", "requires": { "@airgap/coinlib-core": "*", "@airgap/serializer": "*" } }, "@airgap/moonbeam": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/moonbeam/-/moonbeam-0.13.14.tgz", - "integrity": "sha512-uB/sKRsgfas7zdbLKQ4CYpkuf0+gXjSqkALQga9xvR+ZOuzAkpR1wR98QXKpay53zye5BBj8+bOBK7oiOc/j1w==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/moonbeam/-/moonbeam-0.13.15-beta.10.tgz", + "integrity": "sha512-CahZ8Gv+m684KBcjJrHyXdCWsVbFvZUXRcNnIYyR3Iey2OpxTiWZWPKl8FVsq4zl/UeXPB3iZGfOkf/5E5/D0g==", "requires": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -26647,9 +26884,9 @@ } }, "@airgap/polkadot": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/polkadot/-/polkadot-0.13.14.tgz", - "integrity": "sha512-05r0cuY4zm45Ax7xWlRRQNWTLIAKSR4z+ho+DWOY2KQA6iQpu6NwuG6XCasXEeaCzqcs/glgJ3aMWihyvI7IeA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/polkadot/-/polkadot-0.13.15-beta.10.tgz", + "integrity": "sha512-lqDlSx1GfyA9Xsi1UrDfcJkFuWuDeiNqTS6HLokCfR+PO/g3HawKEg3bINtLnv2uAKvclKx8iylbDq+oxZamxA==", "requires": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -26662,17 +26899,17 @@ "integrity": "sha512-IMODbGPTBYKuO5ztiHX9C1PTlhqZvmVWv7m7zj5+VMcbBxrk4+jBAf7FYTH5l+IUsNMaHBOuh8Qq3A1b/pm7jQ==" }, "@airgap/serializer": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/serializer/-/serializer-0.13.14.tgz", - "integrity": "sha512-VJFug2/BABrORd0AuPTB/3QEv4LBt8EQvbQAg9dvt/+HpVooWtZGw4DrFqcqYvMAo3DA77OQ7R55UzGvTBLrDA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/serializer/-/serializer-0.13.15-beta.10.tgz", + "integrity": "sha512-woa1UG/UJQxlLuAxWpxxbHdIyPDGzNiEbdmBMe7HGi0IMnT+4SRqhQcLGBUSoPG4zB2hy00U4eICNGGaJDqhLg==", "requires": { "@airgap/coinlib-core": "*" } }, "@airgap/substrate": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/substrate/-/substrate-0.13.14.tgz", - "integrity": "sha512-VMlcq10OB68y9v81aUQ2LiY3Lk0NIjOPea0jHrAxf9DVu81oLgajHAt0x6g3TcPQDqQ8eRoHeyPAjFnbSNDu3w==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/substrate/-/substrate-0.13.15-beta.10.tgz", + "integrity": "sha512-f+qapP2tx3X4GzcqAZm3RJ7ctAUIOqFLugmzSEeiYTxYdoohfLyxpvMyh2ErpNoIRDQCzraQ8zZ0G9UUr5KTxg==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -26683,9 +26920,9 @@ } }, "@airgap/tezos": { - "version": "0.13.14", - "resolved": "https://registry.npmjs.org/@airgap/tezos/-/tezos-0.13.14.tgz", - "integrity": "sha512-2HDHCMpvS4C6ZF2aqprGZPC+mPKqdH4ZgdCJiv+gSnExhzhtBJXNrqFzycGrrbVihZQnr/wUQ6B+3OIkEfhIhA==", + "version": "0.13.15-beta.10", + "resolved": "https://registry.npmjs.org/@airgap/tezos/-/tezos-0.13.15-beta.10.tgz", + "integrity": "sha512-mvcXr6SDaWOftWXv4IzFpKoDBJx++jH4suubxGqUrvgvJGDEVq5/Ynp6ce3m0nb9lL//T+IF73rmnqCCfkgmMA==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -28746,6 +28983,136 @@ "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-4.0.1.tgz", "integrity": "sha512-BmEyOf3m/hAf8bO4hCX0m5gpQPSgd05mGYl+9E841WUZeJjcYlmiG/EBshAUb2uGCVtyNaG36yPXB0r0Ypg+rw==" }, + "@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "requires": { + "@jridgewell/trace-mapping": "0.3.9" + } + }, + "@dfinity/agent": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/@dfinity/agent/-/agent-0.15.5.tgz", + "integrity": "sha512-Ytn8eo0Gk8QkaCX2X+CS1NYOdCr0ZjanqFyKbR5rY7LGQoVaNzdVHJufzheuTFMhTZs6i/OtaG2BQug4cNIocw==", + "requires": { + "base64-arraybuffer": "^0.2.0", + "bignumber.js": "^9.0.0", + "borc": "^2.1.1", + "js-sha256": "0.9.0", + "simple-cbor": "^0.4.1", + "ts-node": "^10.8.2" + }, + "dependencies": { + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" + }, + "base64-arraybuffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz", + "integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==" + }, + "borc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/borc/-/borc-2.1.2.tgz", + "integrity": "sha512-Sy9eoUi4OiKzq7VovMn246iTo17kzuyHJKomCfpWMlI6RpfN1gk95w7d7gH264nApVLg0HZfcpz62/g4VH1Y4w==", + "requires": { + "bignumber.js": "^9.0.0", + "buffer": "^5.5.0", + "commander": "^2.15.0", + "ieee754": "^1.1.13", + "iso-url": "~0.4.7", + "json-text-sequence": "~0.1.0", + "readable-stream": "^3.6.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "iso-url": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/iso-url/-/iso-url-0.4.7.tgz", + "integrity": "sha512-27fFRDnPAMnHGLq36bWTpKET+eiXct3ENlCcdcMdk+mjXrb2kw3mhBUg1B7ewAC0kVzlOPhADzQgz1SE6Tglog==" + }, + "json-text-sequence": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/json-text-sequence/-/json-text-sequence-0.1.1.tgz", + "integrity": "sha512-L3mEegEWHRekSHjc7+sc8eJhba9Clq1PZ8kMkzf8OxElhXc8O4TS5MwcVlj9aEbm5dr81N90WHC5nAz3UO971w==", + "requires": { + "delimit-stream": "0.1.0" + } + }, + "ts-node": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", + "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "requires": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + } + } + } + }, + "@dfinity/identity-secp256k1": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/@dfinity/identity-secp256k1/-/identity-secp256k1-0.15.5.tgz", + "integrity": "sha512-W0Y1bpuC6Nkl3zZlsFhYpLlaF6yw6uCZOEbLPqNfdUB5jv1fOS8SSsl557L3cG5d9utDLJOA9ejZ8cWxcTEMSw==", + "requires": { + "@dfinity/agent": "^0.15.5", + "bip39": "^3.0.4", + "bs58check": "^2.1.2", + "secp256k1": "^4.0.3" + }, + "dependencies": { + "bip39": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", + "integrity": "sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==", + "requires": { + "@noble/hashes": "^1.2.0" + } + } + } + }, + "@dfinity/nns": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@dfinity/nns/-/nns-0.14.0.tgz", + "integrity": "sha512-qQ3SzihD9hL2Zo0pAC+Ip2snbEtLDL1Aq2JTnDMLur9DEpiCajzhjXfsOy+U1zeSTOc+RUBbbWeLbS5Edsxeig==", + "requires": { + "crc": "^4.3.2", + "crc-32": "^1.2.2", + "google-protobuf": "^3.21.2", + "js-sha256": "^0.9.0", + "randombytes": "^2.1.0" + }, + "dependencies": { + "crc": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/crc/-/crc-4.3.2.tgz", + "integrity": "sha512-uGDHf4KLLh2zsHa8D8hIQ1H/HtFQhyHrc0uhHBcoKGol/Xnb+MPYfUMw7cvON6ze/GUESTudKayDcJC5HnJv1A==" + } + } + }, "@discoveryjs/json-ext": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.2.tgz", @@ -29240,6 +29607,25 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==" + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, "@jsdevtools/coverage-istanbul-loader": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.5.tgz", @@ -29581,6 +29967,11 @@ "tslib": "^2.0.0" } }, + "@noble/hashes": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz", + "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -30322,6 +30713,26 @@ "integrity": "sha512-Z6DoceYb/1xSg5+e+ZlPZ9v0N16ZvZ+wYMraFue4HYrE4ttONKtsvruIRf6t9TBR0YvSOfi1hUU0fJfBLCDYow==", "dev": true }, + "@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + }, + "@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + }, + "@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + }, + "@tsconfig/node16": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", + "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + }, "@types/bn.js": { "version": "4.11.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", @@ -31385,8 +31796,7 @@ "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" }, "argparse": { "version": "1.0.10", @@ -33685,8 +34095,7 @@ "create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "critters": { "version": "0.0.7", @@ -34556,6 +34965,11 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, + "delimit-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/delimit-stream/-/delimit-stream-0.1.0.tgz", + "integrity": "sha512-a02fiQ7poS5CnjiJBAsjGLPp5EwVoGHNeu9sziBd9huppRfsAFIpv5zNLv0V1gbop53ilngAf5Kf331AwcoRBQ==" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -34627,8 +35041,7 @@ "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" }, "diffie-hellman": { "version": "5.0.3", @@ -36678,6 +37091,11 @@ "slash": "^3.0.0" } }, + "google-protobuf": { + "version": "3.21.2", + "resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz", + "integrity": "sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==" + }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -37306,6 +37724,11 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, + "humanize-duration": { + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.28.0.tgz", + "integrity": "sha512-jMAxraOOmHuPbffLVDKkEKi/NeG8dMqP8lGRd6Tbf7JgAeG33jjgPWDbXXU7ypCI0o+oNKJFgbSB9FKVdWNI2A==" + }, "humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -39112,8 +39535,7 @@ "make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" }, "make-fetch-happen": { "version": "8.0.14", @@ -45771,6 +46193,11 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, + "v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -47301,8 +47728,7 @@ "yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" }, "yocto-queue": { "version": "0.1.0", diff --git a/package.json b/package.json index 8240bafce..648c56428 100644 --- a/package.json +++ b/package.json @@ -55,27 +55,27 @@ } }, "dependencies": { - "@airgap/aeternity": "0.13.14", - "@airgap/angular-core": "0.0.36", - "@airgap/angular-ngrx": "0.0.36", - "@airgap/astar": "0.13.14", + "@airgap/aeternity": "0.13.15-beta.10", + "@airgap/angular-core": "0.0.37-beta.17", + "@airgap/angular-ngrx": "0.0.37-beta.17", + "@airgap/astar": "0.13.15-beta.10", "@airgap/beacon-sdk": "3.1.5-beta.0", - "@airgap/bitcoin": "0.13.14", - "@airgap/coinlib-core": "0.13.14", - "@airgap/coreum": "0.13.14", - "@airgap/cosmos": "0.13.14", - "@airgap/cosmos-core": "0.13.14", - "@airgap/crypto": "0.13.14", - "@airgap/ethereum": "0.13.14", - "@airgap/groestlcoin": "0.13.14", - "@airgap/icp": "0.13.14", - "@airgap/module-kit": "0.13.14", - "@airgap/moonbeam": "0.13.14", - "@airgap/polkadot": "0.13.14", + "@airgap/bitcoin": "0.13.15-beta.10", + "@airgap/coinlib-core": "0.13.15-beta.10", + "@airgap/coreum": "0.13.15-beta.10", + "@airgap/cosmos": "0.13.15-beta.10", + "@airgap/cosmos-core": "0.13.15-beta.10", + "@airgap/crypto": "0.13.15-beta.10", + "@airgap/ethereum": "0.13.15-beta.10", + "@airgap/groestlcoin": "0.13.15-beta.10", + "@airgap/icp": "0.13.15-beta.10", + "@airgap/module-kit": "0.13.15-beta.10", + "@airgap/moonbeam": "0.13.15-beta.10", + "@airgap/polkadot": "0.13.15-beta.10", "@airgap/sapling-wasm": "0.0.7", - "@airgap/serializer": "0.13.14", - "@airgap/substrate": "0.13.14", - "@airgap/tezos": "0.13.14", + "@airgap/serializer": "0.13.15-beta.10", + "@airgap/substrate": "0.13.15-beta.10", + "@airgap/tezos": "0.13.15-beta.10", "@angular/animations": "^11.2.9", "@angular/common": "^11.2.9", "@angular/core": "^11.2.9", @@ -147,6 +147,7 @@ "graphql": "^16.0.1", "graphql-request": "^3.6.1", "html-loader": "^2.1.2", + "humanize-duration": "^3.28.0", "ionicons": "^5.5.1", "localforage-cordovasqlitedriver": "^1.7.0", "moment": "^2.29.1", diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 065359e63..bb81e8e5c 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -155,8 +155,10 @@ const routes: Routes = [ }, { path: 'delegation-detail/:id/:publicKey/:protocolID/:addressIndex', + resolve: { + special: DataResolverService + }, canActivate: [ProtocolGuard, ServiceKeyGuard], - loadChildren: () => import('./pages/delegation-detail/delegation-detail.module').then((m) => m.DelegationDetailPageModule) }, { diff --git a/src/app/components/account-edit-popover/account-edit-popover.component.ts b/src/app/components/account-edit-popover/account-edit-popover.component.ts index 96169978b..7812b3ff1 100644 --- a/src/app/components/account-edit-popover/account-edit-popover.component.ts +++ b/src/app/components/account-edit-popover/account-edit-popover.component.ts @@ -66,10 +66,7 @@ export class AccountEditPopoverComponent implements OnInit { this.isTezosKT = true } if (supportsDelegation(this.wallet.protocol)) { - this.isDelegated = await this.operationsProvider.getDelegationStatusOfAddress( - this.wallet.protocol, - this.wallet.receivingPublicAddress - ) + this.isDelegated = await this.operationsProvider.getDelegationStatus(this.wallet) } // tezos end } diff --git a/src/app/components/components.module.ts b/src/app/components/components.module.ts index 6ad5388fc..3a257c713 100644 --- a/src/app/components/components.module.ts +++ b/src/app/components/components.module.ts @@ -40,6 +40,7 @@ import { WidgetAccountSummary } from './widget-account-summary/widget-account-su import { WidgetAccount } from './widget-account/widget-account' import { WidgetAlert } from './widget-alert/widget-alert' import { WidgetIconText } from './widget-icon-text/widget-icon-text' +import { WidgetInputDelay } from './widget-input-delay/widget-input-delay' import { WidgetInputText } from './widget-input-text/widget-input-text' import { WidgetOptionButtonGroup } from './widget-option-button-group/widget-option-button-group' import { WidgetRewardList } from './widget-reward-list/widget-reward-list' @@ -76,6 +77,7 @@ import { WidgetSelector } from './widget-selector/widget-selector' WidgetAccountExtendedDetails, WidgetAlert, WidgetIconText, + WidgetInputDelay, WidgetInputText, WidgetRewardList, WidgetOptionButtonGroup, @@ -126,6 +128,7 @@ import { WidgetSelector } from './widget-selector/widget-selector' WidgetAccountExtendedDetails, WidgetAlert, WidgetIconText, + WidgetInputDelay, WidgetInputText, WidgetRewardList, WidgetOptionButtonGroup, diff --git a/src/app/components/portfolio-item/portfolio-item.ts b/src/app/components/portfolio-item/portfolio-item.ts index 99673ddf2..9899c90d7 100644 --- a/src/app/components/portfolio-item/portfolio-item.ts +++ b/src/app/components/portfolio-item/portfolio-item.ts @@ -1,7 +1,7 @@ import { AmountConverterPipe, ProtocolService } from '@airgap/angular-core' -import { Component, Input } from '@angular/core' -import { AirGapMarketWallet, ICoinDelegateProtocol } from '@airgap/coinlib-core' +import { AirGapMarketWallet } from '@airgap/coinlib-core' import { NetworkType } from '@airgap/coinlib-core/utils/ProtocolNetwork' +import { Component, Input } from '@angular/core' import BigNumber from 'bignumber.js' import { Observable, Subscription } from 'rxjs' @@ -78,10 +78,7 @@ export class PortfolioItemComponent { if (!supportsDelegation(this.wallet.protocol)) { this.isDelegated = null } else { - this.isDelegated = await this.operationsProvider.getDelegationStatusObservableOfAddress( - this.wallet?.protocol as ICoinDelegateProtocol, - this.wallet?.receivingPublicAddress - ) + this.isDelegated = await this.operationsProvider.getDelegationStatusObservable(this.wallet) } } } diff --git a/src/app/components/widget-input-delay/widget-input-delay.html b/src/app/components/widget-input-delay/widget-input-delay.html new file mode 100644 index 000000000..685f261c6 --- /dev/null +++ b/src/app/components/widget-input-delay/widget-input-delay.html @@ -0,0 +1,31 @@ +
+ + + + {{ widget.label | translate }} + + + + + + + + +

+
+
+
+ + + +

{{ widget.errorLabel | translate }}

+
+
+
+
diff --git a/src/app/components/widget-input-delay/widget-input-delay.scss b/src/app/components/widget-input-delay/widget-input-delay.scss new file mode 100644 index 000000000..939a8400b --- /dev/null +++ b/src/app/components/widget-input-delay/widget-input-delay.scss @@ -0,0 +1,17 @@ +.value__container { + .item-inner { + border-bottom-color: transparent !important; + box-shadow: none !important; + } + ion-input { + font-size: 1.4em; + font-weight: bold; + margin: 0; + --padding-top: 12px; + --padding-bottom: 12px; + } + .value--container__input, + .value--container__input .item-inner { + padding-right: 0; + } +} diff --git a/src/app/components/widget-input-delay/widget-input-delay.ts b/src/app/components/widget-input-delay/widget-input-delay.ts new file mode 100644 index 000000000..3926217e1 --- /dev/null +++ b/src/app/components/widget-input-delay/widget-input-delay.ts @@ -0,0 +1,48 @@ +import { Component, Input, OnChanges, SimpleChanges } from '@angular/core' +import { FormGroup } from '@angular/forms' +import BigNumber from 'bignumber.js' +import { Subscription } from 'rxjs' +import { UIInputDelay } from 'src/app/models/widgets/input/UIInputDelay' + +@Component({ + selector: 'widget-input-delay', + templateUrl: 'widget-input-delay.html', + styleUrls: ['widget-input-delay.scss'] +}) +export class WidgetInputDelay implements OnChanges { + @Input() + public widget: UIInputDelay + + @Input() + public widgetForm: FormGroup + + public value: string | undefined + + private valueSubscription: Subscription | undefined + + public ngOnChanges(changes: SimpleChanges): void { + const currentWidget = changes.widget.currentValue as UIInputDelay + this.value = currentWidget.fixedMinValue + + if (changes.widgetForm.previousValue !== changes.widgetForm.currentValue) { + this.valueSubscription?.unsubscribe() + const currentWidgetForm = changes.widgetForm.currentValue as FormGroup + this.valueSubscription = currentWidgetForm.get(this.widget.id).valueChanges.subscribe((value) => { + const control = currentWidgetForm.get(this.widget.id) + if (control.dirty && control.valid && new BigNumber(value).gte(currentWidget.fixedMinValue)) { + this.value = value + } + }) + } + } + + public onRangeChange(event) { + const value: number = event.detail.value + if (isNaN(value)) { + return + } + + this.widgetForm.get(this.widget.id).markAsPristine() + this.widgetForm.patchValue({ [this.widget.id]: event.detail.value.toString() }) + } +} diff --git a/src/app/components/widget-selector/widget-selector.html b/src/app/components/widget-selector/widget-selector.html index 506294dd1..f195a41f8 100644 --- a/src/app/components/widget-selector/widget-selector.html +++ b/src/app/components/widget-selector/widget-selector.html @@ -2,6 +2,7 @@ + diff --git a/src/app/extensions/delegation/CoreumDelegationExtensions.ts b/src/app/extensions/delegation/CoreumDelegationExtensions.ts index 56b463667..19c428ab2 100644 --- a/src/app/extensions/delegation/CoreumDelegationExtensions.ts +++ b/src/app/extensions/delegation/CoreumDelegationExtensions.ts @@ -73,6 +73,7 @@ export class CoreumDelegationExtensions extends V1ProtocolDelegationExtensions, + _publicKey: string, delegator: string, delegatees: string[] ): Promise { @@ -100,8 +101,7 @@ export class CoreumDelegationExtensions extends V1ProtocolDelegationExtensions { const unkownValidators: CosmosValidator[] = await Promise.all( - delegatees - .map((address: string) => adapter.protocolV1.fetchValidator(address)) + delegatees.map((address: string) => adapter.protocolV1.fetchValidator(address)) ) type ValidatorDetails = CosmosValidatorDetails | (CosmosValidator & Pick) @@ -142,6 +142,7 @@ export class CoreumDelegationExtensions extends V1ProtocolDelegationExtensions, + _publicKey: string, address: string ): Promise { const results = await Promise.all([ @@ -179,14 +180,16 @@ export class CoreumDelegationExtensions extends V1ProtocolDelegationExtensions { - return { - label: 'account-transaction-detail.unbonding_completion', - text: `${await this.amountConverterPipe.transformValueOnly(unbondingDetail.balance, adapter, 0)} ${adapter.symbol} - ${ - unbondingDetail.completionTime - }` - } - })) + const unbondingCompletionItems = await Promise.all( + unbondingDetails.map(async (unbondingDetail) => { + return { + label: 'account-transaction-detail.unbonding_completion', + text: `${await this.amountConverterPipe.transformValueOnly(unbondingDetail.balance, adapter, 0)} ${adapter.symbol} - ${ + unbondingDetail.completionTime + }` + } + }) + ) items.splice(3, 0, ...unbondingCompletionItems) @@ -201,7 +204,7 @@ export class CoreumDelegationExtensions extends V1ProtocolDelegationExtensions { const results = await Promise.all([ adapter.protocolV1.fetchValidator(validatorDetails.address), - adapter.protocolV1.fetchSelfDelegation(validatorDetails.address), + adapter.protocolV1.fetchSelfDelegation(validatorDetails.address) ]) const allDetails = results[0] @@ -224,7 +227,10 @@ export class CoreumDelegationExtensions extends V1ProtocolDelegationExtensions, validatorDetails: CosmosValidator): Promise { + private async createValidatorDisplayDetails( + adapter: ICoinDelegateProtocolAdapter, + validatorDetails: CosmosValidator + ): Promise { const details = [] const votingPower = await this.fetchVotingPower(adapter.protocolV1, validatorDetails.operator_address) diff --git a/src/app/extensions/delegation/CosmosDelegationExtensions.ts b/src/app/extensions/delegation/CosmosDelegationExtensions.ts index eecf4096a..25b8e8872 100644 --- a/src/app/extensions/delegation/CosmosDelegationExtensions.ts +++ b/src/app/extensions/delegation/CosmosDelegationExtensions.ts @@ -77,6 +77,7 @@ export class CosmosDelegationExtensions extends V0ProtocolDelegationExtensions { @@ -145,7 +146,7 @@ export class CosmosDelegationExtensions extends V0ProtocolDelegationExtensions { + public async createAccountExtendedDetails(protocol: CosmosProtocol, _publicKey: string, address: string): Promise { const results = await Promise.all([ protocol.getAvailableBalanceOfAddresses([address]), protocol.fetchTotalDelegatedAmount(address), diff --git a/src/app/extensions/delegation/ICPDelegationExtensions.ts b/src/app/extensions/delegation/ICPDelegationExtensions.ts new file mode 100644 index 000000000..79597af48 --- /dev/null +++ b/src/app/extensions/delegation/ICPDelegationExtensions.ts @@ -0,0 +1,797 @@ +import { AmountConverterPipe, ICoinDelegateProtocolAdapter } from '@airgap/angular-core' +import { DelegatorAction } from '@airgap/coinlib-core' +import { ICPProtocol, ICPStakingActionType, ICPUnits } from '@airgap/icp' +import { ICPDelegateeDetails, ICPDelegatorDetails, Neuron } from '@airgap/icp/v1/types/governance' +import { Amount, newAmount, newPublicKey, ProtocolMetadata } from '@airgap/module-kit' +import { DecimalPipe } from '@angular/common' +import { FormBuilder, Validators } from '@angular/forms' +import { TranslateService } from '@ngx-translate/core' +import BigNumber from 'bignumber.js' +import * as humanizeDuration from 'humanize-duration' +import { + AirGapDelegateeDetails, + AirGapDelegationDetails, + AirGapDelegatorAction, + AirGapDelegatorDetails +} from 'src/app/interfaces/IAirGapCoinDelegateProtocol' +import { UIAccountExtendedDetails } from 'src/app/models/widgets/display/UIAccountExtendedDetails' +import { UIAccountSummary } from 'src/app/models/widgets/display/UIAccountSummary' +import { UIIconText } from 'src/app/models/widgets/display/UIIconText' +import { UIInputDelay } from 'src/app/models/widgets/input/UIInputDelay' +import { UIInputWidget } from 'src/app/models/widgets/UIInputWidget' +import { UIWidget } from 'src/app/models/widgets/UIWidget' +import { ShortenStringPipe } from 'src/app/pipes/shorten-string/shorten-string.pipe' +import { DecimalValidator } from 'src/app/validators/DecimalValidator' + +import { V1ProtocolDelegationExtensions } from './base/V1ProtocolDelegationExtensions' + +enum ArgumentName { + FOLLOWEE = 'followee', + AMOUNT = 'amount', + AMOUNT_CONTROL = 'amountControl', + DISSOLVE_DELAY = 'dissolveDelay', + DISSOLVE_DELAY_CONTROL = 'dissolveDelayControl' +} + +type DefaultAmountType = 'min' | 'max' + +export class ICPDelegationExtensions extends V1ProtocolDelegationExtensions { + private static instance: ICPDelegationExtensions + + public static create( + formBuilder: FormBuilder, + decimalPipe: DecimalPipe, + amountConverterPipe: AmountConverterPipe, + shortenStringPipe: ShortenStringPipe, + translateService: TranslateService + ): ICPDelegationExtensions { + if (!ICPDelegationExtensions.instance) { + ICPDelegationExtensions.instance = new ICPDelegationExtensions( + formBuilder, + decimalPipe, + amountConverterPipe, + shortenStringPipe, + translateService + ) + } + + return ICPDelegationExtensions.instance + } + + public delegateeLabel: string = 'delegation-detail-icp.delegatee-label' + public delegateeLabelPlural: string = 'delegation-detail-icp.delegatee-label-plural' + public supportsMultipleDelegations: boolean = true + + private constructor( + private readonly formBuilder: FormBuilder, + private readonly decimalPipe: DecimalPipe, + private readonly amountConverterPipe: AmountConverterPipe, + public readonly shortenStringPipe: ShortenStringPipe, + public readonly translateService: TranslateService + ) { + super() + } + + public async getExtraDelegationDetailsFromAddress( + adapter: ICoinDelegateProtocolAdapter, + publicKey: string, + _delegator: string, + delegatees: string[], + data?: { neuron?: Neuron } + ): Promise { + const metadata = await adapter.protocolV1.getMetadata() + const delegationsDetails = await Promise.all( + delegatees.map((followee) => + adapter.protocolV1.getDelegationDetailsFromPublicKey(newPublicKey(publicKey, 'hex'), [followee], { neuron: data?.neuron }) + ) + ) + + return Promise.all( + delegationsDetails.map(async (details) => { + const [delegator, followee] = await Promise.all([ + this.getExtraDelegatorDetails(adapter, metadata, publicKey, details.delegator, details.delegatees[0].address), + this.getExtraFolloweeDetails(adapter, details.delegatees[0]) + ]) + + return { + delegator, + delegatees: [followee].filter((followee) => !!followee) + } + }) + ) + } + + public async createDelegateesSummary( + adapter: ICoinDelegateProtocolAdapter, + _delegatees: string[], + _data?: { neuron?: Neuron } + ): Promise { + const followees = await adapter.protocolV1.getKnownNeurons() + + return followees.map((neuron) => { + return new UIAccountSummary({ + address: neuron.id?.[0]?.id?.toString() || '', + header: neuron.known_neuron_data?.[0]?.name || '', + description: neuron.known_neuron_data?.[0]?.description[0] || '' + }) + }) + } + + public async createAccountExtendedDetails( + adapter: ICoinDelegateProtocolAdapter, + publicKey: string, + _address: string, + _data?: { neuron?: Neuron } + ): Promise { + const results = await Promise.all([ + adapter.protocolV1.getMetadata(), + adapter.protocolV1.getBalanceOfPublicKey(newPublicKey(publicKey, 'hex')) + ]) + + const metadata = results[0] + const availableBalance = newAmount(results[1].transferable ?? results[1].total).blockchain(metadata.units).value + const totalBalance = newAmount(results[1].total).blockchain(metadata.units).value + const lockedBalance = new BigNumber(totalBalance).minus(availableBalance).toFixed() + + return new UIAccountExtendedDetails({ + items: [ + { + label: 'account-transaction-detail.available_label', + text: `${await this.amountConverterPipe.transformValueOnly(availableBalance, adapter, 0)} ${adapter.symbol}` + }, + { + label: 'account-transaction-detail.delegated_label', + text: `${await this.amountConverterPipe.transformValueOnly(lockedBalance, adapter, 0)} ${adapter.symbol}` + }, + ] + }) + } + + private async createDisplayDetails( + adapter: ICoinDelegateProtocolAdapter, + delegatorDetails: ICPDelegatorDetails + ): Promise { + const details: UIWidget[] = [] + + const subaccountBalanceBN = new BigNumber(delegatorDetails.subaccountBalance) + const stakeBN = delegatorDetails.stake ? new BigNumber(delegatorDetails.stake) : undefined + + if (subaccountBalanceBN.gt(0) && (stakeBN === undefined || !subaccountBalanceBN.eq(stakeBN))) { + details.push( + new UIIconText({ + iconName: 'logo-usd', + text: await this.amountConverterPipe.transform(delegatorDetails.subaccountBalance, { protocol: adapter }), + description: 'delegation-detail-icp.neuron-balance_label' + }) + ) + } + + if (delegatorDetails.stake) { + details.push( + new UIIconText({ + iconName: 'logo-usd', + text: await this.amountConverterPipe.transform(delegatorDetails.stake, { protocol: adapter }), + description: 'delegation-detail-icp.staked_label' + }) + ) + } + + if (delegatorDetails.votingPower) { + details.push( + new UIIconText({ + iconName: 'sync-outline', + text: this.decimalPipe.transform(new BigNumber(delegatorDetails.votingPower).shiftedBy(-adapter.decimals).toString(), '1.0-2'), + description: 'delegation-detail-icp.voting-power_label' + }) + ) + } + + if (delegatorDetails.maturity) { + details.push( + new UIIconText({ + iconName: 'logo-usd', + text: await this.amountConverterPipe.transform(delegatorDetails.maturity, { protocol: adapter }), + description: 'delegation-detail-icp.maturity_label' + }) + ) + } + + if (delegatorDetails.age) { + details.push( + new UIIconText({ + iconName: 'time-outline', + text: humanizeDuration(delegatorDetails.age, { + units: new BigNumber(delegatorDetails.age).gte(24 * 3600) ? ['y', 'd'] : ['h', 'm', 's'], + round: true, + unitMeasures: { + y: 365 * 24 * 3600, + d: 24 * 3600, + h: 3600, + m: 60, + s: 1 + } + }), + description: 'delegation-detail-icp.age_label' + }) + ) + } + + if (delegatorDetails.dissolveDelay) { + details.push( + new UIIconText({ + iconName: 'timer-outline', + text: humanizeDuration(delegatorDetails.dissolveDelay, { + units: new BigNumber(delegatorDetails.dissolveDelay).gte(24 * 3600) ? ['y', 'd'] : ['h', 'm', 's'], + round: true, + unitMeasures: { + y: 365 * 24 * 3600, + d: 24 * 3600, + h: 3600, + m: 60, + s: 1 + } + }), + description: 'delegation-detail-icp.dissolve-delay_label' + }) + ) + } + + return details + } + + private async getExtraFolloweeDetails( + adapter: ICoinDelegateProtocolAdapter, + followeeDetails: ICPDelegateeDetails, + ): Promise { + const currentUsage = new BigNumber(0) + const totalUsage = new BigNumber(0) + + const displayDetails = await this.createFolloweeDisplayDetails(adapter, followeeDetails) + + return { + ...followeeDetails, + status: `delegation-detail-icp.followee-status.${followeeDetails.status}`, + logo: undefined, + usageDetails: { + usage: currentUsage.div(totalUsage), + current: currentUsage, + total: totalUsage + }, + displayDetails + } + } + + private async createFolloweeDisplayDetails( + adapter: ICoinDelegateProtocolAdapter, + followeeDetails: ICPDelegateeDetails + ): Promise { + const details: UIWidget[] = [] + + details.push( + new UIIconText({ + iconName: 'sync-outline', + text: this.decimalPipe.transform(new BigNumber(followeeDetails.votingPower).shiftedBy(-adapter.decimals).toString(), '1.0-2'), + description: 'delegation-detail-icp.voting-power_label' + }) + ) + + return details + } + + private async getExtraDelegatorDetails( + adapter: ICoinDelegateProtocolAdapter, + metadata: ProtocolMetadata, + publicKey: string, + delegatorDetails: ICPDelegatorDetails, + followee: string + ): Promise { + const results = await Promise.all([ + this.createStakeAction(adapter, metadata, publicKey, delegatorDetails, followee), + this.createFollowAction(adapter, metadata, delegatorDetails, followee), + this.createIncreaseDissolveDelayAction(adapter, metadata, delegatorDetails), + this.createMoreDetailsAction(adapter, metadata, delegatorDetails), + this.createDisburseAction(adapter, metadata, delegatorDetails), + this.createStartDissolvingAction(delegatorDetails), + this.createStopDissolvingAction(adapter, metadata, delegatorDetails) + ]) + + const stakeAction = results[0] + const followAction = results[1] + const increaseDissolveDelayAction = results[2] + const moreDetailsAction = results[3] + const disburseAction = results[4] + const startDissolvingAction = results[5] + const stopDissolvingAction = results[6] + + + const displayDetails = await this.createDisplayDetails(adapter, delegatorDetails) + + return { + ...delegatorDetails, + mainActions: [ + stakeAction, + followAction, + increaseDissolveDelayAction, + moreDetailsAction, + stopDissolvingAction, + disburseAction + ].filter((action) => !!action), + secondaryActions: [startDissolvingAction].filter((action) => !!action), + displayDetails + } + } + + private async createStakeAction( + adapter: ICoinDelegateProtocolAdapter, + metadata: ProtocolMetadata, + publicKey: string, + delegatorDetails: ICPDelegatorDetails, + followee: string + ): Promise { + const maxStake = await adapter.protocolV1.getMaxStakingAmount(newPublicKey(publicKey, 'hex')) + const isStaking = new BigNumber(delegatorDetails.subaccountBalance).gt(0) + const isFollowing = delegatorDetails.delegatees.includes(followee) + + const getDescription = async (action: DelegatorAction) => { + if (action.type === ICPStakingActionType.STAKE_AND_FOLLOW) { + if (!isStaking && !isFollowing) { + return this.translateService.instant('delegation-detail-icp.stake-and-follow.not-staking-not-following_text', { + minStake: await this.amountConverterPipe.transform(newAmount(1, 'ICP').blockchain(metadata.units).value, { protocol: adapter }), + maxStake: await this.amountConverterPipe.transform(newAmount(maxStake).blockchain(metadata.units).value, { protocol: adapter }) + }) + } + + if (isStaking && !isFollowing) { + return this.translateService.instant('delegation-detail-icp.stake-and-follow.staking-not-following_text', { + neuronBalance: await this.amountConverterPipe.transform(delegatorDetails.subaccountBalance, { protocol: adapter }), + maxStake: await this.amountConverterPipe.transform(newAmount(maxStake).blockchain(metadata.units).value, { protocol: adapter }) + }) + } + + if (isStaking && isFollowing) { + return this.translateService.instant('delegation-detail-icp.stake-and-follow.staking-following_text', { + neuronBalance: await this.amountConverterPipe.transform(delegatorDetails.subaccountBalance, { protocol: adapter }), + maxStake: await this.amountConverterPipe.transform(newAmount(maxStake).blockchain(metadata.units).value, { protocol: adapter }) + }) + } + } + + return '' + } + + const getMinAmount = (action: DelegatorAction): Amount => { + if (action.type === ICPStakingActionType.STAKE_AND_FOLLOW) { + return isStaking ? newAmount(0, 'blockchain') : newAmount(1, 'ICP') + } + + return newAmount(1, 'blockchain') + } + + const getMaxAmount = (_action: DelegatorAction) => { + return maxStake + } + + return this.createMainDelegatorAction( + adapter, + metadata, + delegatorDetails.availableActions ?? [], + [ICPStakingActionType.STAKE_AND_FOLLOW], + async (_) => 'delegation-detail-icp.stake-and-follow.label', + getDescription, + { + followee, + + getMinAmount, + getMaxAmount, + + minDelay: new BigNumber(delegatorDetails.dissolveDelay ?? 0), + maxDelay: new BigNumber(8 * 365.25 * 24 * 3600) /* 8 years */ + } + ) + } + + private async createFollowAction( + adapter: ICoinDelegateProtocolAdapter, + metadata: ProtocolMetadata, + delegatorDetails: ICPDelegatorDetails, + followee: string + ): Promise { + return this.createMainDelegatorAction( + adapter, + metadata, + delegatorDetails.availableActions ?? [], + [ICPStakingActionType.FOLLOW], + async (_) => 'delegation-detail-icp.follow.label', + async (_) => 'delegation-detail-icp.follow.text', + { followee } + ) + } + + private async createIncreaseDissolveDelayAction( + adapter: ICoinDelegateProtocolAdapter, + metadata: ProtocolMetadata, + delegatorDetails: ICPDelegatorDetails + ): Promise { + const dissolveDelay = delegatorDetails.dissolveDelay ?? '0' + const humanizedDissolveDelay = humanizeDuration(dissolveDelay, { + units: new BigNumber(dissolveDelay).gte(24 * 3600) ? ['y', 'd'] : ['h', 'm', 's'], + round: true, + unitMeasures: { + y: 365 * 24 * 3600, + d: 24 * 3600, + h: 3600, + m: 60, + s: 1 + } + }) + + const maxDissolveDelay = new BigNumber(8 * 365.25 * 24 * 3600) /* 8 years */ + const humanizedMaxDissolveDelay = humanizeDuration(maxDissolveDelay.toString(), { + units: ['y', 'mo', 'd'], + round: true, + unitMeasures: { + y: 365 * 24 * 3600, + mo: 30 * 24 * 3600, + d: 24 * 3600, + h: 3600, + m: 60, + s: 1 + }, + largest: 2 + }) + + return this.createMainDelegatorAction( + adapter, + metadata, + delegatorDetails.availableActions ?? [], + [ICPStakingActionType.INCREASE_DISSOLVE_DELAY], + async (_) => 'delegation-detail-icp.increase-dissolve-delay.label', + async (_) => this.translateService.instant('delegation-detail-icp.increase-dissolve-delay.text', { + dissolveDelay: humanizedDissolveDelay, + maxDissolveDelay: humanizedMaxDissolveDelay + }), + { + minDelay: new BigNumber(delegatorDetails.dissolveDelay ?? 0), + maxDelay: maxDissolveDelay + } + ) + } + + private async createMoreDetailsAction( + adapter: ICoinDelegateProtocolAdapter, + metadata: ProtocolMetadata, + delegatorDetails: ICPDelegatorDetails + ): Promise { + return this.createMainDelegatorAction( + adapter, + metadata, + delegatorDetails.availableActions ?? [], + [ICPStakingActionType.GET_STAKING_DETAILS], + async (_) => 'delegation-detail-icp.more-details.label', + async (_) => 'delegation-detail-icp.more-details.text' + ) + } + + private createDisburseAction( + adapter: ICoinDelegateProtocolAdapter, + metadata: ProtocolMetadata, + delegatorDetails: ICPDelegatorDetails + ): Promise { + return this.createMainDelegatorAction( + adapter, + metadata, + delegatorDetails.availableActions ?? [], + [ICPStakingActionType.DISBURSE_AND_UNFOLLOW], + async (_) => 'delegation-detail-icp.disburse.label', + async (_) => 'delegation-detail-icp.disburse.text' + ) + } + + private createStartDissolvingAction(delegatorDetails: ICPDelegatorDetails): AirGapDelegatorAction | null { + if (delegatorDetails.availableActions?.find((action) => action.type === ICPStakingActionType.START_DISSOLVING)) { + return { + type: ICPStakingActionType.START_DISSOLVING, + label: 'delegation-detail-icp.start-dissolving.label', + iconName: 'close-outline' + } + } + + return null + } + + private createStopDissolvingAction( + adapter: ICoinDelegateProtocolAdapter, + metadata: ProtocolMetadata, + delegatorDetails: ICPDelegatorDetails + ): Promise { + const dissolveDelay = delegatorDetails.dissolveDelay ?? '0' + const humanizedDissolveDelay = humanizeDuration(dissolveDelay, { + units: new BigNumber(dissolveDelay).gte(24 * 3600) ? ['y', 'd'] : ['h', 'm', 's'], + round: true, + unitMeasures: { + y: 365 * 24 * 3600, + d: 24 * 3600, + h: 3600, + m: 60, + s: 1 + } + }) + + return this.createMainDelegatorAction( + adapter, + metadata, + delegatorDetails.availableActions ?? [], + [ICPStakingActionType.STOP_DISSOLVING], + async (_) => 'delegation-detail-icp.stop-dissolving.label', + async (_) => this.translateService.instant('delegation-detail-icp.stop-dissolving.text', { + dissolveDelay: humanizedDissolveDelay + }) + ) + } + + // tslint:disable-next-line: cyclomatic-complexity + private async createMainDelegatorAction( + adapter: ICoinDelegateProtocolAdapter, + metadata: ProtocolMetadata, + availableActions: DelegatorAction[], + types: ICPStakingActionType[], + getLabel: (action: DelegatorAction) => Promise, + getDescription: (action: DelegatorAction) => Promise, + configuration: { + followee?: string + + getMinAmount?: (action: DelegatorAction) => Amount + getMaxAmount?: (action: DelegatorAction) => Amount + getDefaultAmountType?: (action: DelegatorAction) => DefaultAmountType + + minDelay?: BigNumber + fixedMinDelay?: BigNumber + maxDelay?: BigNumber + } = {} + ): Promise { + const action = availableActions.find((action) => types.includes(action.type)) + if (!action) { + return null + } + + const { + followee: neuronIdArgName, + amount: amountArgName, + amountControl: amountControlArgName, + delay: delayArgName, + delayControl: delayControlArgName + } = this.resolveMainArgumentNames(action.type) + + const followee = configuration.followee + + const minAmount = configuration.getMinAmount ? configuration.getMinAmount(action) : undefined + const maxAmount = configuration.getMaxAmount ? configuration.getMaxAmount(action) : undefined + const defaultAmountType: DefaultAmountType = configuration.getDefaultAmountType ? configuration.getDefaultAmountType(action) : 'max' + + const minDelay = configuration.minDelay + const fixedMinDelay = configuration.fixedMinDelay ?? minDelay + const maxDelay = configuration.maxDelay + + let controls = {} + + if (neuronIdArgName) { + if (followee === undefined) { + return null + } + + controls = Object.assign(controls, { + [neuronIdArgName]: followee + }) + } + const inputWidgets: UIInputWidget[] = [] + + if (amountArgName && amountControlArgName) { + const minBlockchainAmount = minAmount ? newAmount(minAmount).blockchain(metadata.units) : undefined + const maxBlockchainAmount = maxAmount ? newAmount(maxAmount).blockchain(metadata.units) : undefined + + if (minAmount === undefined || maxAmount === undefined || maxBlockchainAmount.toBigNumber().lt(minBlockchainAmount.toBigNumber())) { + return null + } + + const minAmountFormatted = newAmount(minAmount).convert('ICP', metadata.units).value + const maxAmountFormatted = newAmount(maxAmount).convert('ICP', metadata.units).value + + const defaultBlockchainAmount = defaultAmountType === 'min' ? minBlockchainAmount : maxBlockchainAmount + const defaultAmountFormatted = defaultAmountType === 'min' ? minAmountFormatted : maxAmountFormatted + + controls = Object.assign(controls, { + [amountArgName]: defaultBlockchainAmount.value, + [amountControlArgName]: [ + defaultAmountFormatted, + Validators.compose([ + Validators.required, + Validators.min(new BigNumber(minAmountFormatted).toNumber()), + Validators.max(new BigNumber(maxAmountFormatted).toNumber()), + DecimalValidator.validate(adapter.decimals) + ]) + ] + }) + inputWidgets.push( + this.createAmountWidget(amountControlArgName, maxAmountFormatted, minAmountFormatted, { + onValueChanged: (value: string) => { + form.patchValue({ [amountArgName]: new BigNumber(value).shiftedBy(adapter.decimals).toFixed() }) + }, + defaultValue: defaultAmountFormatted + }) + ) + } + + if (delayArgName && delayControlArgName) { + if (maxDelay === undefined || minDelay === undefined || maxDelay.lt(minDelay)) { + return null + } + + const minDelayEligibleForRewardsDays = new BigNumber(6 * 30) // 6 months + const minDelayEligibleForRewards = minDelayEligibleForRewardsDays.times(24 * 3600) + + const minDelayDays = minDelay.div(24 * 3600) + const fixedMinDelayDays = BigNumber.max(fixedMinDelay.div(24 * 3600), minDelayEligibleForRewardsDays) + const maxDelayDays = maxDelay.div(24 * 3600) + + const votingPowerMultiplier = new BigNumber(1).div(maxDelay) + + controls = Object.assign(controls, { + [delayArgName]: fixedMinDelay.toString(), + [delayControlArgName]: [ + fixedMinDelayDays.toFixed(0, BigNumber.ROUND_CEIL), + Validators.compose([ + Validators.required, + Validators.min(minDelayDays.toNumber()), + Validators.max(maxDelayDays.toNumber()), + DecimalValidator.validate(0) + ]) + ] + }) + + const humanizedMinDelayEligibleForRewardsInDays = humanizeDuration(minDelayEligibleForRewardsDays.toFixed(0, BigNumber.ROUND_CEIL), { + units: ['d'], + unitMeasures: { + d: 1 + } + }) + const humanizedMinDelayEligibleForRewards = humanizeDuration(minDelayEligibleForRewardsDays.toFixed(0, BigNumber.ROUND_CEIL), { + units: ['y', 'mo', 'd'], + round: true, + unitMeasures: { + y: 365, + mo: 30, + d: 1 + }, + largest: 2 + }) + + const humanizedFixedMinDelayInDays = humanizeDuration(fixedMinDelayDays.toFixed(0, BigNumber.ROUND_CEIL), { + units: ['d'], + unitMeasures: { + d: 1 + } + }) + const humanizedFixedMinDelay = humanizeDuration(fixedMinDelayDays.toFixed(0, BigNumber.ROUND_CEIL), { + units: ['y', 'mo', 'd'], + round: true, + unitMeasures: { + y: 365, + mo: 30, + d: 1 + }, + largest: 2 + }) + + const humanizedMaxDelayInDays = humanizeDuration(maxDelayDays.toFixed(0, BigNumber.ROUND_CEIL), { + units: ['d'], + unitMeasures: { + d: 1 + } + }) + const humanizedMaxDelay = humanizeDuration(maxDelayDays.toFixed(0, BigNumber.ROUND_CEIL), { + units: ['y', 'mo', 'd'], + round: true, + unitMeasures: { + y: 365, + mo: 30, + d: 1 + }, + largest: 2 + }) + + inputWidgets.push( + new UIInputDelay({ + id: delayControlArgName, + label: 'delegation-detail-icp.form.dissolve-delay.label', + inputType: 'days', + minValue: minDelayDays.toFixed(0, BigNumber.ROUND_CEIL), + fixedMinValue: fixedMinDelayDays.toFixed(0, BigNumber.ROUND_CEIL), + maxValue: maxDelayDays.toFixed(0, BigNumber.ROUND_CEIL), + createExtraLabel: (value: string) => { + const currentDelayDays = new BigNumber(value) + if (currentDelayDays.isNaN()) { + return '' + } + + const duration = humanizeDuration(value, { + units: ['y', 'mo', 'd'], + round: true, + unitMeasures: { + y: 365, + mo: 30, + d: 1 + }, + largest: 2 + }) + + const currentDelay = currentDelayDays.times(24 * 3600) + if (currentDelay.lt(minDelay) || currentDelay.gt(maxDelay)) { + return '' + } + + const currentVotingPowerMultiplier = currentDelay.gte(minDelayEligibleForRewards) ? votingPowerMultiplier : new BigNumber(0) + + const currentVotingPower = currentDelay.times(currentVotingPowerMultiplier).plus(1) + + const label = currentDelay.gte(minDelayEligibleForRewards) + ? 'delegation-detail-icp.form.dissolve-delay.extra-label' + : 'delegation-detail-icp.form.dissolve-delay.extra-label-no-rewards' + + return this.translateService.instant(label, { + minDelay: `${humanizedMinDelayEligibleForRewards} (${humanizedMinDelayEligibleForRewardsInDays})`, + duration, + votingPower: currentVotingPower.toFixed(2, BigNumber.ROUND_HALF_FLOOR) + }) + }, + onValueChanged: (value: string) => { + form.patchValue({ [delayArgName]: new BigNumber(value).times(24 * 3600).toString() }) + }, + errorLabel: fixedMinDelay.gt(minDelayEligibleForRewards) + ? this.translateService.instant('delegation-detail-icp.form.dissolve-delay.invalid-decrease', { + minDelay: `${humanizedFixedMinDelay} (${humanizedFixedMinDelayInDays})`, + maxDelay: `${humanizedMaxDelay} (${humanizedMaxDelayInDays})` + }) + : this.translateService.instant('delegation-detail-icp.form.dissolve-delay.invalid-state', { + minDelay: `${humanizedMinDelayEligibleForRewards} (${humanizedMinDelayEligibleForRewardsInDays})`, + maxDelay: `${humanizedMaxDelay} (${humanizedMaxDelayInDays})` + }) + }) + ) + } + + const form = this.formBuilder.group(controls) + const [label, description] = await Promise.all([getLabel(action), getDescription(action)]) + + return { + type: action.type, + form, + label, + description, + args: inputWidgets + } + } + + private resolveMainArgumentNames(mainAction: ICPStakingActionType): { followee?: string; amount?: string; amountControl?: string; delay?: string; delayControl?: string } { + switch (mainAction) { + case ICPStakingActionType.STAKE_AND_FOLLOW: + return { + followee: ArgumentName.FOLLOWEE, + amount: ArgumentName.AMOUNT, + amountControl: ArgumentName.AMOUNT_CONTROL, + delay: ArgumentName.DISSOLVE_DELAY, + delayControl: ArgumentName.DISSOLVE_DELAY_CONTROL + } + case ICPStakingActionType.FOLLOW: + return { + followee: ArgumentName.FOLLOWEE + } + case ICPStakingActionType.INCREASE_DISSOLVE_DELAY: + return { + delay: ArgumentName.DISSOLVE_DELAY, + delayControl: ArgumentName.DISSOLVE_DELAY_CONTROL + } + default: + return {} + } + } +} diff --git a/src/app/extensions/delegation/MoonbeamDelegationExtensions.ts b/src/app/extensions/delegation/MoonbeamDelegationExtensions.ts index 13aea3bcc..99b392c05 100644 --- a/src/app/extensions/delegation/MoonbeamDelegationExtensions.ts +++ b/src/app/extensions/delegation/MoonbeamDelegationExtensions.ts @@ -64,6 +64,7 @@ export class MoonbeamDelegationExtensions extends V0ProtocolDelegationExtensions public async getExtraDelegationDetailsFromAddress( protocol: MoonbeamProtocol, + _publicKey: string, delegator: string, delegatees: string[] ): Promise { @@ -132,7 +133,7 @@ export class MoonbeamDelegationExtensions extends V0ProtocolDelegationExtensions current: ownBond, total: totalBond }, - displayDetails, + displayDetails } } @@ -491,7 +492,7 @@ export class MoonbeamDelegationExtensions extends V0ProtocolDelegationExtensions alerts.push( new UIAlert({ title: 'delegation-detail-moonbeam.alert.collator-oversubscribed.title', - description: this.translateService.instant('delegation-detail-moonbeam.alert.collator-oversubscribed.description', { + description: this.translateService.instant('delegation-detail-moonbeam.alert.collator-oversubscribed.description', { maxTopDelegations: maxTopDelegations.toString(), minStakingAmount: await this.amountConverterPipe.transform(delegationDetails.collatorDetails.minEligibleBalance, { protocol, diff --git a/src/app/extensions/delegation/SubstrateDelegationExtensions.ts b/src/app/extensions/delegation/SubstrateDelegationExtensions.ts index a9a90cd89..81cff27c7 100644 --- a/src/app/extensions/delegation/SubstrateDelegationExtensions.ts +++ b/src/app/extensions/delegation/SubstrateDelegationExtensions.ts @@ -99,6 +99,7 @@ export class SubstrateDelegationExtensions extends V0ProtocolDelegationExtension public async getExtraDelegationDetailsFromAddress( protocol: SubstrateDelegateProtocol, + _publicKey: string, delegator: string, delegatees: string[] ): Promise { diff --git a/src/app/extensions/delegation/TezosDelegationExtensions.ts b/src/app/extensions/delegation/TezosDelegationExtensions.ts index 37cebcf6e..71766d836 100644 --- a/src/app/extensions/delegation/TezosDelegationExtensions.ts +++ b/src/app/extensions/delegation/TezosDelegationExtensions.ts @@ -77,6 +77,7 @@ export class TezosDelegationExtensions extends V0ProtocolDelegationExtensions { diff --git a/src/app/extensions/delegation/base/ProtocolDelegationExtensions.ts b/src/app/extensions/delegation/base/ProtocolDelegationExtensions.ts index 09c95ab73..1aebb52a5 100644 --- a/src/app/extensions/delegation/base/ProtocolDelegationExtensions.ts +++ b/src/app/extensions/delegation/base/ProtocolDelegationExtensions.ts @@ -1,3 +1,4 @@ +// tslint:disable: max-classes-per-file import { AirGapMarketWallet, ICoinDelegateProtocol } from '@airgap/coinlib-core' import BigNumber from 'bignumber.js' @@ -49,17 +50,19 @@ export class DefaultProtocolDelegationExtensions { return [] } - public getRewardDisplayDetails(_protocol: T, _delegator: string, _delegatees: string[]): Promise { + public getRewardDisplayDetails(_protocol: T, _delegator: string, _delegatees: string[], _data?: any): Promise { return undefined // by default display no rewards } - public async createDelegateesSummary(protocol: T, delegatees: string[]): Promise { + public async createDelegateesSummary(protocol: T, delegatees: string[], _data?: any): Promise { const delegateesDetails = await Promise.all(delegatees.map((delegatee) => protocol.getDelegateeDetails(delegatee))) return delegateesDetails.map( (details) => @@ -71,7 +74,7 @@ export class DefaultProtocolDelegationExtensions { + public async createAccountExtendedDetails(_protocol: T, _publicKey: string, _address: string, _data?: any): Promise { // default implementation provides no details return new UIAccountExtendedDetails({ items: [] diff --git a/src/app/extensions/delegation/base/V0ProtocolDelegationExtensions.ts b/src/app/extensions/delegation/base/V0ProtocolDelegationExtensions.ts index 1eda897aa..f4231d73b 100644 --- a/src/app/extensions/delegation/base/V0ProtocolDelegationExtensions.ts +++ b/src/app/extensions/delegation/base/V0ProtocolDelegationExtensions.ts @@ -72,21 +72,23 @@ export abstract class V0ProtocolDelegationExtensions { - return this.defaults.getExtraDelegationDetailsFromAddress(protocol, delegator, delegatees) + return this.defaults.getExtraDelegationDetailsFromAddress(protocol, publicKey, delegator, delegatees, data) } - public getRewardDisplayDetails(protocol: T, delegator: string, delegatees: string[]): Promise { - return this.defaults.getRewardDisplayDetails(protocol, delegator, delegatees) + public getRewardDisplayDetails(protocol: T, delegator: string, delegatees: string[], data?: any): Promise { + return this.defaults.getRewardDisplayDetails(protocol, delegator, delegatees, data) } - public async createDelegateesSummary(protocol: T, delegatees: string[]): Promise { - return this.defaults.createDelegateesSummary(protocol, delegatees) + public async createDelegateesSummary(protocol: T, delegatees: string[], data?: any): Promise { + return this.defaults.createDelegateesSummary(protocol, delegatees, data) } - public async createAccountExtendedDetails(protocol: T, address: string): Promise { - return this.defaults.createAccountExtendedDetails(protocol, address) + public async createAccountExtendedDetails(protocol: T, publicKey: string, address: string, data?: any): Promise { + return this.defaults.createAccountExtendedDetails(protocol, publicKey, address, data) } } diff --git a/src/app/extensions/delegation/base/V1ProtocolDelegationExtensions.ts b/src/app/extensions/delegation/base/V1ProtocolDelegationExtensions.ts index c540459c0..db3df935d 100644 --- a/src/app/extensions/delegation/base/V1ProtocolDelegationExtensions.ts +++ b/src/app/extensions/delegation/base/V1ProtocolDelegationExtensions.ts @@ -7,7 +7,9 @@ import { UIAccountSummary } from 'src/app/models/widgets/display/UIAccountSummar import { UIRewardList } from 'src/app/models/widgets/display/UIRewardList' import { DefaultProtocolDelegationExtensions, ProtocolDelegationExtensions } from './ProtocolDelegationExtensions' -export abstract class V1ProtocolDelegationExtensions extends ProtocolDelegationExtensions { +export abstract class V1ProtocolDelegationExtensions< + T extends AirGapOnlineProtocol & AirGapDelegateProtocol +> extends ProtocolDelegationExtensions { public static async load( adapter: ICoinDelegateProtocolAdapter, extensionFactory: () => Promise> @@ -41,7 +43,9 @@ export abstract class V1ProtocolDelegationExtensions> = new DefaultProtocolDelegationExtensions() + private readonly defaults: DefaultProtocolDelegationExtensions< + ICoinDelegateProtocolAdapter + > = new DefaultProtocolDelegationExtensions() public abstract delegateeLabel: string public abstract delegateeLabelPlural: string @@ -52,32 +56,38 @@ export abstract class V1ProtocolDelegationExtensions, + adapter: ICoinDelegateProtocolAdapter, + publicKey: string, delegator: string, - delegatees: string[] + delegatees: string[], + data?: any ): Promise { - return this.defaults.getExtraDelegationDetailsFromAddress(adapter, delegator, delegatees) + return this.defaults.getExtraDelegationDetailsFromAddress(adapter, publicKey, delegator, delegatees, data) } public getRewardDisplayDetails( - adapter: ICoinDelegateProtocolAdapter, - delegator: string, - delegatees: string[] + adapter: ICoinDelegateProtocolAdapter, + delegator: string, + delegatees: string[], + data?: any ): Promise { - return this.defaults.getRewardDisplayDetails(adapter, delegator, delegatees) + return this.defaults.getRewardDisplayDetails(adapter, delegator, delegatees, data) } public async createDelegateesSummary( - adapter: ICoinDelegateProtocolAdapter, - delegatees: string[] + adapter: ICoinDelegateProtocolAdapter, + delegatees: string[], + data?: any ): Promise { - return this.defaults.createDelegateesSummary(adapter, delegatees) + return this.defaults.createDelegateesSummary(adapter, delegatees, data) } public async createAccountExtendedDetails( - adapter: ICoinDelegateProtocolAdapter, - address: string + adapter: ICoinDelegateProtocolAdapter, + publicKey: string, + address: string, + data?: any ): Promise { - return this.defaults.createAccountExtendedDetails(adapter, address) + return this.defaults.createAccountExtendedDetails(adapter, publicKey, address, data) } } diff --git a/src/app/interfaces/IAirGapCoinDelegateProtocol.ts b/src/app/interfaces/IAirGapCoinDelegateProtocol.ts index 146969b17..bd5b9103b 100644 --- a/src/app/interfaces/IAirGapCoinDelegateProtocol.ts +++ b/src/app/interfaces/IAirGapCoinDelegateProtocol.ts @@ -53,8 +53,13 @@ export interface IAirGapCoinDelegateProtocol extends ICoinDelegateProtocol { delegateeLabelPlural: string supportsMultipleDelegations: boolean - getRewardDisplayDetails(delegator: string, delegatees: string[]): Promise - getExtraDelegationDetailsFromAddress(delegator: string, delegatees: string[]): Promise - createDelegateesSummary(delegatees: string[]): Promise - createAccountExtendedDetails(address: string): Promise + getRewardDisplayDetails(delegator: string, delegatees: string[], data?: any): Promise + getExtraDelegationDetailsFromAddress( + publicKey: string, + delegator: string, + delegatees: string[], + data?: any + ): Promise + createDelegateesSummary(delegatees: string[], data?: any): Promise + createAccountExtendedDetails(publicKey: string, address: string, data?: any): Promise } diff --git a/src/app/models/ActionGroup.ts b/src/app/models/ActionGroup.ts index 2ff6c21e6..1c2e3e7c5 100644 --- a/src/app/models/ActionGroup.ts +++ b/src/app/models/ActionGroup.ts @@ -159,7 +159,9 @@ export class ActionGroup { } private async getTezosShieldedTezActions(): Promise[]> { - const shieldedTezProtocol = (await this.callerContext.protocolService.getProtocol(MainProtocolSymbols.XTZ_SHIELDED)) as TezosShieldedTezProtocol + const shieldedTezProtocol = (await this.callerContext.protocolService.getProtocol( + MainProtocolSymbols.XTZ_SHIELDED + )) as TezosShieldedTezProtocol const isContractSet = (await shieldedTezProtocol.getOptions()).config.contractAddress !== undefined const setContract: ButtonAction = new ButtonAction( @@ -269,9 +271,9 @@ export class ActionGroup { return [delegateButtonAction] } - private getICPActions(): Action[] { - // TODO: staking - return [] + private async getICPActions(): Promise[]> { + const delegateButtonAction = this.createDelegateButtonAction() + return [delegateButtonAction] } private async addKtAddress(xtzWallet: AirGapMarketWallet, index: number, ktAddresses: string[]): Promise { diff --git a/src/app/models/widgets/UIInputWidget.ts b/src/app/models/widgets/UIInputWidget.ts index 299179009..15963dd5f 100644 --- a/src/app/models/widgets/UIInputWidget.ts +++ b/src/app/models/widgets/UIInputWidget.ts @@ -43,7 +43,7 @@ export abstract class UIInputWidget extends UIWidget { } this.formControl.valueChanges.subscribe((value) => { - if (value) { + if (value !== undefined || value !== null) { this.value = value this.onValueChanged() } diff --git a/src/app/models/widgets/UIWidget.ts b/src/app/models/widgets/UIWidget.ts index 87ba802e2..9f4d7519a 100644 --- a/src/app/models/widgets/UIWidget.ts +++ b/src/app/models/widgets/UIWidget.ts @@ -6,6 +6,7 @@ export enum UIWidgetType { ACCOUNT_EXTENDED_DETAILS = 'account_extended_details', ALERT = 'alert', ICON_TEXT = 'icon_text', + INPUT_DELAY = 'input_delay', INPUT_TEXT = 'input_text', REWARD_LIST = 'reward_list', OPTION_BUTTON_GROUP = 'option_button_group' diff --git a/src/app/models/widgets/input/UIInputDelay.ts b/src/app/models/widgets/input/UIInputDelay.ts new file mode 100644 index 000000000..3641b2269 --- /dev/null +++ b/src/app/models/widgets/input/UIInputDelay.ts @@ -0,0 +1,67 @@ +import { AirGapMarketWallet } from '@airgap/coinlib-core' + +import { UIInputWidget, UIInputWidgetConfig } from '../UIInputWidget' +import { UIWidgetType } from '../UIWidget' + +type InputType = 'milliseconds' | 'seconds' | 'minutes' | 'hours' | 'days' | 'months' | 'years' + +export interface UIInputDelayConfig extends UIInputWidgetConfig { + inputType?: InputType + userInputType?: InputType + + label: string + + minValue: string + fixedMinValue?: string + maxValue: string + defaultValue?: string + + extraLabel?: string + createExtraLabel?: (value: string, wallet?: AirGapMarketWallet) => string + errorLabel?: string + + onValueChanged?: (value?: string, widget?: UIInputDelay) => void +} + +export class UIInputDelay extends UIInputWidget { + public readonly type = UIWidgetType.INPUT_DELAY + public readonly inputType: InputType + + public label: string + + public readonly minValue: string + public readonly fixedMinValue: string + public readonly maxValue: string + + public extraLabel?: string + public createExtraLabel?: (value: string) => string + public errorLabel?: string + + constructor(config: UIInputDelayConfig) { + super(config) + + this.inputType = config.inputType ?? 'milliseconds' + + this.label = config.label + + this.minValue = config.minValue + this.fixedMinValue = config.fixedMinValue ?? this.minValue + this.maxValue = config.maxValue + this.value = config.defaultValue || config.fixedMinValue + + this.createExtraLabel = config.createExtraLabel ? (value: string) => config.createExtraLabel(value, this.wallet) : undefined + this.extraLabel = config.extraLabel || this.createExtraLabel ? this.createExtraLabel(this.value) : undefined + this.errorLabel = config.errorLabel + + } + + public onValueChanged() { + if (this.createExtraLabel) { + this.extraLabel = this.createExtraLabel(this.value) + } + + if (this.onValueChangedCallback) { + this.onValueChangedCallback(this.value, this) + } + } +} diff --git a/src/app/pages/account-transaction-list/account-transaction-list.ts b/src/app/pages/account-transaction-list/account-transaction-list.ts index 9af39e9e9..f47f4a93e 100644 --- a/src/app/pages/account-transaction-list/account-transaction-list.ts +++ b/src/app/pages/account-transaction-list/account-transaction-list.ts @@ -2,7 +2,6 @@ import { ProtocolService } from '@airgap/angular-core' import { AirGapMarketWallet, IAirGapTransaction, - ICoinDelegateProtocol, MainProtocolSymbols, SubProtocolSymbols, } from '@airgap/coinlib-core' @@ -354,10 +353,7 @@ export class AccountTransactionListPage { // Tezos public async isDelegated(): Promise { - const isDelegated = await this.operationsProvider.checkDelegated( - this.wallet.protocol as ICoinDelegateProtocol, - this.wallet.receivingPublicAddress - ) + const isDelegated = await this.operationsProvider.checkDelegated(this.wallet) this.isKtDelegated = isDelegated // const action = isDelegated ? this.getStatusAction() : this.getDelegateAction() // this.replaceAction(ActionType.DELEGATE, action) diff --git a/src/app/pages/delegation-detail/delegation-detail.html b/src/app/pages/delegation-detail/delegation-detail.html index 8d30bfa16..b0a7d82c0 100644 --- a/src/app/pages/delegation-detail/delegation-detail.html +++ b/src/app/pages/delegation-detail/delegation-detail.html @@ -18,93 +18,128 @@ - - -
- - - - - -

- -

-

- -

-
-
-
-
-
-
- - - - - {{ "delegation-detail.change-delegatee_label" | translate: { delegateeLabel: (delegateeLabel | translate) } }} - - - - - -

{{ ((delegateeDetails$ | async)?.status | translate) | titlecase }}

-
- -
-
+ +
+ + + + + +

+ +

+

+ +

+
+
+
+
+ + + + + +

+ +

+

+ +

+
+
- - - - - - {{ (delegateeDetails$ | async).usageDetails.usage.toNumber() * 100 | number: '1.2-2' }}% - - - -
+ + + + + + + {{ "delegation-detail.change-delegatee_label" | translate: { delegateeLabel: (delegateeLabel | translate) } }} + + + + + +

{{ (delegateeDetails.value?.status | translate) | titlecase }}

+
+ +
+
+
+
+ + + + + + {{ delegateeDetails.value.usageDetails.usage.toNumber() * 100 | number: '1.2-2' }}% + + +
+

+ +

+
+

- -
- - - - {{ (delegateeDetails$ | async).usageDetails.current.toFixed() | amountConverter: { protocol: wallet.protocol, maxDigits: 3 } - | async }} / {{ (delegateeDetails$ | async).usageDetails.total.toFixed() | amountConverter: { protocol: wallet.protocol, - maxDigits: 3 } | async }} - - - -
+ + + + + {{ delegateeDetails.value.usageDetails.current.toFixed() | amountConverter: { protocol: wallet.protocol, maxDigits: 3 } + | async }} / {{ delegateeDetails.value.usageDetails.total.toFixed() | amountConverter: { protocol: wallet.protocol, + maxDigits: 3 } | async }} + + +
+ +
+
- -
- - - + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + +

+ +

+

+ +

+
+
-
- - + @@ -119,77 +154,90 @@

- - - + + + - + - + - - - - - {{ main.label | translate }} - - + + + + + + {{ main.label | translate }} + + -
- - - - -

-
-
- - -
- -
- -
-
+
+ + + + +

+
+
+ + +
+ +
+ +
+
+
- -
- - +
+
+
- - - -

- {{ "delegation-detail.your-delegation_label" | translate }} -

-
-
-
+ + + +

+ {{ "delegation-detail.your-delegation_label" | translate }} +

+
+
+
- - - - - - - - - - + + + + + + + + + + + - - - + + + + + +

+ +

+

+ +

+
+
+ @@ -202,12 +250,12 @@

-
-
-
-
+ +
+
+ - +

@@ -218,7 +266,7 @@

- + diff --git a/src/app/pages/delegation-detail/delegation-detail.ts b/src/app/pages/delegation-detail/delegation-detail.ts index df7489c35..1e353a3ab 100644 --- a/src/app/pages/delegation-detail/delegation-detail.ts +++ b/src/app/pages/delegation-detail/delegation-detail.ts @@ -1,12 +1,13 @@ -import { AmountConverterPipe } from '@airgap/angular-core' +import { AmountConverterPipe, UIResource, UIResourceStatus } from '@airgap/angular-core' import { AirGapMarketWallet } from '@airgap/coinlib-core' import { IACMessageType } from '@airgap/serializer' -import { Component } from '@angular/core' +import { Component, OnDestroy, OnInit } from '@angular/core' import { FormBuilder, FormGroup } from '@angular/forms' import { ActivatedRoute, Router } from '@angular/router' -import { LoadingController, NavController, PopoverController, ToastController } from '@ionic/angular' +import { LoadingController, NavController, PopoverController, ToastController, ViewWillEnter } from '@ionic/angular' import { OverlayEventDetail } from '@ionic/core' -import { BehaviorSubject } from 'rxjs' +import { BehaviorSubject, Subject } from 'rxjs' +import { takeUntil } from 'rxjs/operators' import { DelegateActionPopoverComponent } from 'src/app/components/delegate-action-popover/delegate-action-popover.component' import { supportsAirGapDelegation } from 'src/app/helpers/delegation' import { @@ -32,26 +33,37 @@ import { isType } from 'src/app/utils/utils' templateUrl: './delegation-detail.html', styleUrls: ['./delegation-detail.scss'] }) -export class DelegationDetailPage { +export class DelegationDetailPage implements OnInit, OnDestroy, ViewWillEnter { + public UIResourceStatus: typeof UIResourceStatus = UIResourceStatus + public wallet: AirGapMarketWallet public showOverflowMenu: boolean public delegationForms: Map = new Map() - public delegationAlertWidgets: UIAlert[] | undefined + public delegationAlertWidgets: UIResource = { status: UIResourceStatus.IDLE, value: undefined } public delegateeLabel: string public delegateeLabelPlural: string - public delegateeAccountWidget: UIAccount + public delegateeAccountWidget: UIResource = { status: UIResourceStatus.IDLE, value: undefined } - public delegatorBalanceWidget: UIIconText + public delegatorBalanceWidget: UIResource = { status: UIResourceStatus.IDLE, value: undefined } public activeDelegatorAction: string | null = null public activeDelegatorActionConfirmButton: string | null = null - public delegateeDetails$: BehaviorSubject = new BehaviorSubject(null) - public delegatorDetails$: BehaviorSubject = new BehaviorSubject(null) - public rewardDisplay$: BehaviorSubject = new BehaviorSubject(null) + public delegateeDetails$: BehaviorSubject> = new BehaviorSubject>({ + status: UIResourceStatus.IDLE, + value: undefined + }) + public delegatorDetails$: BehaviorSubject> = new BehaviorSubject>({ + status: UIResourceStatus.IDLE, + value: undefined + }) + public rewardDisplay$: BehaviorSubject> = new BehaviorSubject>({ + status: UIResourceStatus.IDLE, + value: undefined + }) public canProceed: boolean = true public hasRewardDetails: boolean | undefined = undefined @@ -59,7 +71,7 @@ export class DelegationDetailPage { public get shouldDisplaySegmentButtons(): boolean { const details = this.delegatorDetails$.value - return details.mainActions && details.mainActions.some((action) => !!action.description || !!action.args) + return details.value?.mainActions && details.value.mainActions.some((action) => !!action.description || !!action.args) } private get isAirGapDelegatee(): boolean { @@ -83,6 +95,17 @@ export class DelegationDetailPage { private protocolID: string private addressIndex + private data$: BehaviorSubject + + private _ngDestroyed$: Subject | undefined + private get ngDestroyed$(): Subject { + if (this._ngDestroyed$ === undefined) { + this._ngDestroyed$ = new Subject() + } + + return this._ngDestroyed$ + } + constructor( private readonly router: Router, private readonly navController: NavController, @@ -96,9 +119,11 @@ export class DelegationDetailPage { private readonly formBuilder: FormBuilder, private readonly amountConverter: AmountConverterPipe, public readonly accountProvider: AccountProvider - ) {} + ) { + this.data$ = new BehaviorSubject(this.loadNavigationData()) + } - ngOnInit() { + public ngOnInit(): void { this.publicKey = this.route.snapshot.params.publicKey this.protocolID = this.route.snapshot.params.protocolID this.addressIndex = this.route.snapshot.params.addressIndex @@ -110,17 +135,41 @@ export class DelegationDetailPage { this.wallet = this.accountProvider.walletByPublicKeyAndProtocolAndAddressIndex(this.publicKey, this.protocolID, this.addressIndex) this.extensionsService.loadDelegationExtensions().then(() => { - this.initView() + this.initView(this.data$.value) }) } + public ngOnDestroy(): void { + this._ngDestroyed$?.next() + this._ngDestroyed$?.complete() + this._ngDestroyed$ = undefined + } + + public ionViewWillEnter(): void { + const previousData = this.data$.value + const currentData = this.loadNavigationData() + + if (previousData !== currentData) { + this.data$.next(currentData) + } + } + + private loadNavigationData(): any { + if (this.route.snapshot.data.special) { + const info = this.route.snapshot.data.special + return info?.data ?? info + } + + return undefined + } + public filterVisible(widgets?: UIWidget[]): UIWidget[] { return widgets ? widgets.filter((widget) => widget.isVisible) : [] } public async presentEditPopover(event: Event): Promise { const delegatorDetails = this.delegatorDetails$.value - const secondaryActions = delegatorDetails ? delegatorDetails.secondaryActions : undefined + const secondaryActions = delegatorDetails.value ? delegatorDetails.value.secondaryActions : undefined const popover: HTMLIonPopoverElement = await this.popoverController.create({ component: DelegateActionPopoverComponent, @@ -155,26 +204,26 @@ export class DelegationDetailPage { return } - if (!delegatorDetails.mainActions || delegatorDetails.mainActions.length === 0) { + if (!delegatorDetails.value?.mainActions || delegatorDetails.value.mainActions.length === 0) { this.navController.back() return } - this.callAction(delegatorDetails.mainActions, type) + this.callAction(delegatorDetails.value.mainActions, type) } public callSecondaryAction(type: string) { const delegatorDetails = this.delegatorDetails$.value - if (!delegatorDetails) { + if (!delegatorDetails.value) { return } - this.callAction(delegatorDetails.secondaryActions || [], type) + this.callAction(delegatorDetails.value.secondaryActions || [], type) } public onActiveActionChange(activeDelegatorAction: string | null) { - const activeAction = this.delegatorDetails$.value.mainActions - ? this.delegatorDetails$.value.mainActions.find((action) => action.type.toString() === activeDelegatorAction) + const activeAction = this.delegatorDetails$.value.value?.mainActions + ? this.delegatorDetails$.value.value.mainActions.find((action) => action.type.toString() === activeDelegatorAction) : null this.activeDelegatorAction = activeDelegatorAction @@ -188,7 +237,8 @@ export class DelegationDetailPage { delegateeLabel: this.delegateeLabel, delegateeLabelPlural: this.delegateeLabelPlural, areMultipleDelegationsSupported: this.areMultipleDelegationsSupported, - currentDelegatees: this.delegatorDetails$.value.delegatees, + currentDelegatees: this.delegatorDetails$.value.value?.delegatees, + data: this.data$.value, callback: (address: string) => { this.changeDisplayedDetails(address) } @@ -200,7 +250,7 @@ export class DelegationDetailPage { .catch(handleErrorSentry(ErrorCategory.NAVIGATION)) } - private initView() { + private initView(data: any) { this.delegateeLabel = supportsAirGapDelegation(this.wallet.protocol) ? this.wallet.protocol.delegateeLabel : 'delegation-detail.default-delegatee-label' @@ -215,7 +265,8 @@ export class DelegationDetailPage { this.subscribeObservables() - this.operations.getCurrentDelegatees(this.wallet).then((addresses) => { + // tslint:disable-next-line: no-floating-promises + this.operations.getCurrentDelegatees(this.wallet, data).then((addresses) => { if (addresses) { this.delegateeAddress$.next(addresses[0]) } @@ -223,53 +274,73 @@ export class DelegationDetailPage { } private subscribeObservables() { - this.delegateeAddress$.subscribe(async (address) => { - if (address) { - this.updateDisplayedDetails(null) - this.updateDisplayedRewards(null) + this.data$.pipe(takeUntil(this.ngDestroyed$)).subscribe(async (data) => { + const currentDelegatees = await this.operations.getCurrentDelegatees(this.wallet, data) + const address = currentDelegatees[0] ?? this.delegateeAddress$.value + this.loadDelegationDetails(address, data) + }) - this.operations.getDelegationDetails(this.wallet, [address]).then((details) => { - if (details && details.length > 0) { - this.updateDisplayedDetails(details) - } - }) - this.operations.getRewardDisplayDetails(this.wallet, [address]).then((rewards) => { - this.hasRewardDetails = rewards !== undefined - if (rewards) { - this.updateDisplayedRewards(rewards) - } - }) + this.delegateeAddress$.pipe(takeUntil(this.ngDestroyed$)).subscribe((address) => { + if (address) { + this.loadDelegationDetails(address, this.data$.value) } }) - this.delegateeDetails$.subscribe((details) => { - this.delegateeAccountWidget = details - ? new UIAccount({ - name: details.name, - address: details.address, - logo: details.logo, - shortenAddress: true - }) - : null + this.delegateeDetails$.pipe(takeUntil(this.ngDestroyed$)).subscribe((details) => { + this.delegateeAccountWidget = { + status: details.status, + value: details.value + ? new UIAccount({ + name: details.value.name, + address: details.value.address, + logo: details.value.logo, + shortenAddress: true + }) + : undefined + } }) - this.delegatorDetails$.subscribe(async (details) => { + this.delegatorDetails$.pipe(takeUntil(this.ngDestroyed$)).subscribe(async (details) => { this.showOverflowMenu = - !(this.isAirGapDelegatee || this.hideAirGapOverflow) || (details && details.secondaryActions && details.secondaryActions.length > 0) - - if (details) { - this.delegatorBalanceWidget = new UIIconText({ - iconName: 'wallet-outline', - text: await this.amountConverter.transform(details.balance, { - protocol: this.wallet.protocol, - maxDigits: this.wallet.protocol.decimals - }), - description: 'delegation-detail.your-balance_label' - }) + !(this.isAirGapDelegatee || this.hideAirGapOverflow) || (details && details.value?.secondaryActions && details.value?.secondaryActions.length > 0) + + this.delegatorBalanceWidget = { + status: details.status, + value: details.value + ? new UIIconText({ + iconName: 'wallet-outline', + text: await this.amountConverter.transform(details.value.balance, { + protocol: this.wallet.protocol, + maxDigits: this.wallet.protocol.decimals + }), + description: 'delegation-detail.your-balance_label' + }) + : undefined + } - this.setupAllActions(details) + if (details.value) { + this.setupAllActions(details.value) this.setupFormObservers() - this.initActiveDelegatorAction(details) + this.initActiveDelegatorAction(details.value) + } + }) + } + + private loadDelegationDetails(address: string, data: any) { + this.updateDisplayedDetails({ status: UIResourceStatus.LOADING, value: undefined }) + this.updateDisplayedRewards({ status: UIResourceStatus.LOADING, value: undefined }) + + // tslint:disable-next-line: no-floating-promises + this.operations.getDelegationDetails(this.wallet, [address], data).then((details) => { + if (details && details.length > 0) { + this.updateDisplayedDetails({ status: UIResourceStatus.SUCCESS, value: details }) + } + }) + // tslint:disable-next-line: no-floating-promises + this.operations.getRewardDisplayDetails(this.wallet, [address], data).then((rewards) => { + this.hasRewardDetails = rewards !== undefined + if (rewards) { + this.updateDisplayedRewards({ status: UIResourceStatus.SUCCESS, value: rewards }) } }) } @@ -317,7 +388,7 @@ export class DelegationDetailPage { private setupFormObservers() { Array.from(this.delegationForms.entries()).forEach(([type, formGroup]) => { - formGroup.valueChanges.subscribe(() => { + formGroup.valueChanges.pipe(takeUntil(this.ngDestroyed$)).subscribe(() => { if (this.activeDelegatorAction === type.toString()) { setTimeout(() => { this.canProceed = formGroup.valid @@ -332,15 +403,24 @@ export class DelegationDetailPage { this.onActiveActionChange(activeAction ? activeAction.type.toString() : null) } - private updateDisplayedDetails(details: AirGapDelegationDetails[] | null) { + private updateDisplayedDetails(details: UIResource) { // TODO: support multiple cases - this.delegationAlertWidgets = details ? details[0].alerts : undefined + this.delegationAlertWidgets = { + status: details.status, + value: details.value ? details.value[0].alerts : undefined + } - this.delegateeDetails$.next(details ? details[0].delegatees[0] : null) - this.delegatorDetails$.next(details ? details[0].delegator : null) + this.delegateeDetails$.next({ + status: details.status, + value: details.value ? details.value[0].delegatees[0] : undefined + }) + this.delegatorDetails$.next({ + status: details.status, + value: details.value ? details.value[0].delegator : undefined + }) } - private updateDisplayedRewards(rewardDisplay: UIRewardList) { + private updateDisplayedRewards(rewardDisplay: UIResource) { this.rewardDisplay$.next(rewardDisplay) } diff --git a/src/app/pages/delegation-list/delegation-list.page.ts b/src/app/pages/delegation-list/delegation-list.page.ts index 1ac82b70c..d8c7443e4 100644 --- a/src/app/pages/delegation-list/delegation-list.page.ts +++ b/src/app/pages/delegation-list/delegation-list.page.ts @@ -63,6 +63,7 @@ export class DelegationListPage { this.areMultipleDelegationsSupported = info.areMultipleDelegationsSupported this.callback = info.callback + // tslint:disable-next-line: no-floating-promises this.operations.getDelegateesSummary(this.wallet, info.currentDelegatees).then((summary: UIAccountSummary[]) => { this.currentDelegatees = summary.filter( (summary) => summary.address !== undefined && info.currentDelegatees.includes(summary.address) diff --git a/src/app/pages/transaction-confirm/transaction-confirm.ts b/src/app/pages/transaction-confirm/transaction-confirm.ts index fddfb8809..b63f5beff 100644 --- a/src/app/pages/transaction-confirm/transaction-confirm.ts +++ b/src/app/pages/transaction-confirm/transaction-confirm.ts @@ -1,8 +1,9 @@ -import { ProtocolService } from '@airgap/angular-core' +import { ICoinProtocolAdapter, ProtocolService } from '@airgap/angular-core' import { BeaconRequestOutputMessage, BeaconResponseInputMessage } from '@airgap/beacon-sdk' import { AirGapMarketWallet, ICoinProtocol, MainProtocolSymbols, SignedTransaction } from '@airgap/coinlib-core' import { NetworkType } from '@airgap/coinlib-core/utils/ProtocolNetwork' import { RawEthereumTransaction } from '@airgap/ethereum' +import { ICPActionType, ICPModule, ICPProtocol, ICPSignedTransaction } from '@airgap/icp' import { IACMessageDefinitionObject, IACMessageType } from '@airgap/serializer' import { TezosSaplingProtocol } from '@airgap/tezos' import { Component } from '@angular/core' @@ -36,6 +37,7 @@ export class TransactionConfirmPage { public txInfos: [string, ICoinProtocol, BeaconRequestOutputMessage | { transaction: RawEthereumTransaction; id: string }][] = [] public protocols: ICoinProtocol[] = [] + public wallet: AirGapMarketWallet | undefined constructor( private readonly loadingCtrl: LoadingController, @@ -86,6 +88,7 @@ export class TransactionConfirmPage { this.txInfos.push([(messageObject.payload as SignedTransaction).transaction, selectedProtocol, request]) this.protocols.push(selectedProtocol) + this.wallet = wallet }) } @@ -100,6 +103,14 @@ export class TransactionConfirmPage { } } + if (this.protocols.length === 1 && this.protocols[0].identifier === MainProtocolSymbols.ICP) { + const transaction = this.txInfos[0][0] + const handled = await this.interceptICPTransaction(this.protocols[0], transaction) + if (handled) { + return + } + } + const loading = await this.loadingCtrl.create({ message: 'Broadcasting...' }) @@ -318,4 +329,38 @@ export class TransactionConfirmPage { this.dataService.setData(DataServiceKey.ACCOUNTS, info) this.router.navigateByUrl(`/select-wallet/${DataServiceKey.ACCOUNTS}`).catch(handleErrorSentry(ErrorCategory.NAVIGATION)) } + + private async interceptICPTransaction(protocol: ICoinProtocol, transaction: string): Promise { + const adapter = protocol as ICoinProtocolAdapter + + const icpModule = new ICPModule() + const v3SerializerCompanion = await icpModule.createV3SerializerCompanion() + const signedTransaction = await v3SerializerCompanion.fromTransactionSignResponse(adapter.identifier, { transaction, accountIdentifier: '' }) as ICPSignedTransaction + if (signedTransaction.transactions.some(({ actionType }) => actionType === ICPActionType.GET_NEURON_INFO)) { + return this.loadICPFullNeuron(adapter, signedTransaction) + } + + return false + } + + private async loadICPFullNeuron(adapter: ICoinProtocolAdapter, transaction: ICPSignedTransaction): Promise { + if (this.wallet === undefined) { + return false + } + + const data = (await adapter.protocolV1.sendQuery(transaction))[0] + if ('Err' in data) { + throw new Error(data.Err.error_message) + } + + const info = { + neuron: data.Ok + } + this.dataService.setData(DataServiceKey.DETAIL, info) + this.router + .navigateByUrl(`/delegation-detail/${DataServiceKey.DETAIL}/${this.wallet.publicKey}/${adapter.identifier}/${this.wallet.addressIndex}`, { replaceUrl: true }) + .catch(handleErrorSentry(ErrorCategory.NAVIGATION)) + + return true + } } diff --git a/src/app/services/extensions/extensions.service.ts b/src/app/services/extensions/extensions.service.ts index a7b0b53be..bc5f843f5 100644 --- a/src/app/services/extensions/extensions.service.ts +++ b/src/app/services/extensions/extensions.service.ts @@ -18,11 +18,14 @@ import { TezosDelegationExtensions } from '../../extensions/delegation/TezosDele import { ShortenStringPipe } from '../../pipes/shorten-string/shorten-string.pipe' import { CoinlibService } from '../coinlib/coinlib.service' import { V1ProtocolDelegationExtensions } from 'src/app/extensions/delegation/base/V1ProtocolDelegationExtensions' +import { ICPDelegationExtensions } from 'src/app/extensions/delegation/ICPDelegationExtensions' @Injectable({ providedIn: 'root' }) export class ExtensionsService { + private extensionsLoaded: boolean = false + private v0Extensions: [new () => ICoinDelegateProtocol, () => Promise>][] = [ [ KusamaProtocol, @@ -96,6 +99,18 @@ export class ExtensionsService { this.shortenStringPipe, this.translateService ) + ], + [ + + MainProtocolSymbols.ICP, + async () => + ICPDelegationExtensions.create( + this.formBuilder, + this.decimalPipe, + this.amountConverterPipe, + this.shortenStringPipe, + this.translateService + ) ] ] @@ -111,10 +126,16 @@ export class ExtensionsService { ) {} public async loadDelegationExtensions(): Promise { + if (this.extensionsLoaded) { + return + } + await Promise.all([ this.loadV0Extensions(), this.loadV1Extensions() ]) + + this.extensionsLoaded = true } private async loadV0Extensions(): Promise { @@ -126,12 +147,25 @@ export class ExtensionsService { private async loadV1Extensions(): Promise { await Promise.all( this.v1Extensions.map(async ([protocolIdentifier, extensionFactory]) => { - const protocol = await this.protocolService.getProtocol(protocolIdentifier) - if (!(protocol instanceof ICoinDelegateProtocolAdapter)) { + try { + const networks = await this.protocolService.getNetworksForProtocol(protocolIdentifier) + await Promise.all( + networks.map(async (network) => { + try { + const protocol = await this.protocolService.getProtocol(protocolIdentifier, network) + if (!(protocol instanceof ICoinDelegateProtocolAdapter)) { + return + } + + await V1ProtocolDelegationExtensions.load(protocol, extensionFactory) + } catch { + return + } + }) + ) + } catch { return } - - V1ProtocolDelegationExtensions.load(protocol, extensionFactory) }) ) } diff --git a/src/app/services/operations/operations.ts b/src/app/services/operations/operations.ts index be4b107fc..0f85e7e9b 100644 --- a/src/app/services/operations/operations.ts +++ b/src/app/services/operations/operations.ts @@ -14,6 +14,7 @@ import { MainProtocolSymbols, SubProtocolSymbols } from '@airgap/coinlib-core' +import { ProtocolErrorType } from '@airgap/coinlib-core/errors' import { CosmosTransaction } from '@airgap/cosmos' import { RawEthereumTransaction } from '@airgap/ethereum' import { IACMessageDefinitionObjectV3, IACMessageType } from '@airgap/serializer' @@ -62,7 +63,7 @@ export class OperationsProvider { private readonly saplingService: SaplingService ) {} - public async getDelegateesSummary(wallet: AirGapMarketWallet, delegatees: string[]): Promise { + public async getDelegateesSummary(wallet: AirGapMarketWallet, delegatees: string[], data?: any): Promise { const protocol = wallet.protocol if (!supportsDelegation(protocol)) { return Promise.reject('Protocol does not support delegation.') @@ -71,7 +72,7 @@ export class OperationsProvider { if (supportsAirGapDelegation(protocol)) { return protocol.createDelegateesSummary(delegatees) } else { - const delegateesDetails = await Promise.all(delegatees.map((delegatee) => protocol.getDelegateeDetails(delegatee))) + const delegateesDetails = await Promise.all(delegatees.map((delegatee) => protocol.getDelegateeDetails(delegatee, data))) return delegateesDetails.map( (details) => new UIAccountSummary({ @@ -83,26 +84,32 @@ export class OperationsProvider { } } - public async getAccountExtendedDetails(wallet: AirGapMarketWallet): Promise { + public async getAccountExtendedDetails(wallet: AirGapMarketWallet, data?: any): Promise { const protocol = wallet.protocol if (!supportsDelegation(protocol)) { return Promise.reject('Protocol does not support delegation.') } if (supportsAirGapDelegation(protocol)) { - return protocol.createAccountExtendedDetails(wallet.receivingPublicAddress) + return protocol.createAccountExtendedDetails(wallet.publicKey, wallet.receivingPublicAddress, data) } else { return new UIAccountExtendedDetails({ items: [] }) } } - public async getCurrentDelegatees(wallet: AirGapMarketWallet): Promise { + public async getCurrentDelegatees(wallet: AirGapMarketWallet, data?: any): Promise { const protocol = wallet.protocol if (!supportsDelegation(protocol)) { return Promise.reject('Protocol does not support delegation.') } - const current = await protocol.getCurrentDelegateesForAddress(wallet.receivingPublicAddress) + const current = await protocol.getCurrentDelegateesForAddress(wallet.receivingPublicAddress, data).catch((e) => { + if (e.code === ProtocolErrorType.UNSUPPORTED) { + return protocol.getCurrentDelegateesForPublicKey(wallet.publicKey, data) + } else { + throw e + } + }) if (current.length === 0) { let defaultDelegatee: string if (supportsAirGapDelegation(protocol)) { @@ -114,41 +121,57 @@ export class OperationsProvider { return current } - public async getDelegatorDetails(wallet: AirGapMarketWallet): Promise { + public async getDelegatorDetails(wallet: AirGapMarketWallet, data?: any): Promise { const protocol = wallet.protocol if (!supportsDelegation(protocol)) { return Promise.reject('Protocol does not support delegation.') } - return protocol.getDelegatorDetailsFromAddress(wallet.receivingPublicAddress) + return protocol.getDelegatorDetailsFromAddress(wallet.receivingPublicAddress, data).catch((e) => { + if (e.code === ProtocolErrorType.UNSUPPORTED) { + return protocol.getDelegatorDetailsFromPublicKey(wallet.publicKey, data) + } else { + throw e + } + }) } - public async getDelegationDetails(wallet: AirGapMarketWallet, delegatees: string[]): Promise { + public async getDelegationDetails(wallet: AirGapMarketWallet, delegatees: string[], data?: any): Promise { const protocol = wallet.protocol if (!supportsDelegation(protocol)) { return Promise.reject('Protocol does not support delegation.') } return supportsAirGapDelegation(protocol) - ? protocol.getExtraDelegationDetailsFromAddress(wallet.receivingPublicAddress, delegatees) - : [await this.getDefaultDelegationDetails(protocol, wallet.receivingPublicAddress, delegatees)] + ? protocol.getExtraDelegationDetailsFromAddress(wallet.publicKey, wallet.receivingPublicAddress, delegatees, data) + : [await this.getDefaultDelegationDetails(protocol, wallet.publicKey, wallet.receivingPublicAddress, delegatees, data)] } - public async getRewardDisplayDetails(wallet: AirGapMarketWallet, delegatees: string[]): Promise { + public async getRewardDisplayDetails(wallet: AirGapMarketWallet, delegatees: string[], data?: any): Promise { const protocol = wallet.protocol if (!supportsDelegation(protocol)) { return Promise.reject('Protocol does not support delegation.') } - return supportsAirGapDelegation(protocol) ? protocol.getRewardDisplayDetails(wallet.receivingPublicAddress, delegatees) : undefined + return supportsAirGapDelegation(protocol) + ? protocol.getRewardDisplayDetails(wallet.receivingPublicAddress, delegatees, data) + : undefined } private async getDefaultDelegationDetails( protocol: ICoinDelegateProtocol, - delegator: string, - delegatees: string[] + delegatorPublicKey: string, + delegatorAddress: string, + delegatees: string[], + data?: any ): Promise { - const details = await protocol.getDelegationDetailsFromAddress(delegator, delegatees) + const details = await protocol.getDelegationDetailsFromAddress(delegatorAddress, delegatees, data).catch((e) => { + if (e.code === ProtocolErrorType.UNSUPPORTED) { + return protocol.getDelegationDetailsFromPublicKey(delegatorPublicKey, delegatees, data) + } else { + throw e + } + }) const [delegatorDetails, delegateesDetails] = await Promise.all([ this.getDefaultDelegatorDetails(details.delegator, delegatees), @@ -290,11 +313,11 @@ export class OperationsProvider { this.delegationStatuses.next(this.delegationStatuses.getValue().set(address, delegated)) } - public async getDelegationStatusOfAddress(protocol: ICoinDelegateProtocol, address: string, refresh: boolean = false) { - const delegationStatus = this.delegationStatuses.getValue().get(address) + public async getDelegationStatus(wallet: AirGapMarketWallet, refresh: boolean = false) { + const delegationStatus = this.delegationStatuses.getValue().get(wallet.receivingPublicAddress) if (refresh || delegationStatus === undefined) { - const isDelegated = await this.checkDelegated(protocol, address) - this.setDelegationStatusOfAddress(address, isDelegated) + const isDelegated = await this.checkDelegated(wallet) + this.setDelegationStatusOfAddress(wallet.receivingPublicAddress, isDelegated) return isDelegated } else { @@ -302,10 +325,10 @@ export class OperationsProvider { } } - public async getDelegationStatusObservableOfAddress(protocol: ICoinDelegateProtocol, address: string) { - await this.getDelegationStatusOfAddress(protocol, address) + public async getDelegationStatusObservable(wallet: AirGapMarketWallet) { + await this.getDelegationStatus(wallet) - return this.delegationStatuses.pipe(map((delegationStatuses) => delegationStatuses.get(address))) + return this.delegationStatuses.pipe(map((delegationStatuses) => delegationStatuses.get(wallet.receivingPublicAddress))) } public refreshAllDelegationStatuses(wallets: AirGapMarketWallet[]) { @@ -313,9 +336,7 @@ export class OperationsProvider { const address = entry[0] const wallet = wallets.find((wallet) => wallet.receivingPublicAddress === address && supportsDelegation(wallet.protocol)) if (wallet) { - this.getDelegationStatusOfAddress(wallet.protocol as ICoinDelegateProtocol, address, true).catch( - handleErrorSentry(ErrorCategory.OPERATIONS_PROVIDER) - ) + this.getDelegationStatus(wallet, true).catch(handleErrorSentry(ErrorCategory.OPERATIONS_PROVIDER)) } }) } @@ -376,8 +397,18 @@ export class OperationsProvider { ] } - public async checkDelegated(protocol: ICoinDelegateProtocol, address: string): Promise { - return supportsDelegation(protocol) ? protocol.isAddressDelegating(address) : false + public async checkDelegated(wallet: AirGapMarketWallet): Promise { + const protocol = wallet.protocol + + return supportsDelegation(protocol) + ? protocol.isAddressDelegating(wallet.receivingPublicAddress).catch((e) => { + if (e.code === ProtocolErrorType.UNSUPPORTED) { + return protocol.isPublicKeyDelegating(wallet.publicKey) + } else { + throw e + } + }) + : false } public async prepareTransaction( @@ -418,7 +449,9 @@ export class OperationsProvider { }) } else if (wallet.protocol.identifier === MainProtocolSymbols.XTZ && TezosSaplingAddress.isZetAddress(address)) { const protocols: ICoinProtocol[] = (await this.protocolService.getProtocolsForAddress(address)).filter( - (protocol: ICoinProtocol) => protocol.identifier !== MainProtocolSymbols.XTZ && protocol.options.network.identifier === wallet.protocol.options.network.identifier + (protocol: ICoinProtocol) => + protocol.identifier !== MainProtocolSymbols.XTZ && + protocol.options.network.identifier === wallet.protocol.options.network.identifier ) if (protocols.length > 1) { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 762e3ba3b..60acb5edf 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -722,6 +722,59 @@ } } }, + "delegation-detail-icp": { + "delegatee-label": "Followee", + "delegatee-label-plural": "Followees", + "voting-power_label": "Voting Power", + "neuron-balance_label": "Neuron Subaccount Balance", + "staked_label": "Staked", + "maturity_label": "Maturity", + "age_label": "Age", + "dissolve-delay_label": "Dissolve Delay", + "followee-status": { + "unknown": "Unknown (load more details)", + "followed": "Followed", + "not-followed": "Not Folllowed" + }, + "stake-and-follow": { + "label": "Follow", + "not-staking-not-following_text": "Follow this neuron and delegate your stake.

Currently you're not staking, select the amount you want to stake. You can stake from {{ minStake }} up to {{ maxStake }} (after transaction fees).", + "staking-not-following_text": "Follow this neuron and delegate your stake.

You have currently {{ neuronBalance }} staked. You can additionally stake up to {{ maxStake }} (after transaction fees).", + "staking-following_text": "You're following this neuron. Increase your stake to gain more voting power.

You have currently {{ neuronBalance }} staked. You can additionally stake up to {{ maxStake }} (after transaction fees)." + }, + "follow": { + "label": "Follow", + "text": "Follow this neuron." + }, + "increase-dissolve-delay": { + "label": "Set Delay", + "text": "The Dissolve Delay determines how much voting power you have and how long you'll wait for your funds to unlock once you start dissolving your neuron. Your current Dissolve Delay is set to {{ dissolveDelay }} and you can increase it up to {{ maxDissolveDelay }}." + }, + "more-details": { + "label": "More Details", + "text": "Full neuron details are meant to be private therefore access to a private key is required to fetch them. Create and sign a query transaction to load more data." + }, + "disburse": { + "label": "Disburse", + "text": "You neuron has dissolved, withdraw the unlocked tokens." + }, + "start-dissolving": { + "label": "Start Dissolving" + }, + "stop-dissolving": { + "label": "Stop Dissolving", + "text": "Your neuron is currently dissolving, your funds will be unlocked in {{ dissolveDelay }}. Stop dissolving to cancel the process." + }, + "form": { + "dissolve-delay": { + "label": "Dissolve Delay (in days)", + "extra-label": "{{ duration }} (Voting Power {{ votingPower }}x)", + "extra-label-no-rewards": "{{ duration }} (Voting Power {{ votingPower }}x)

Warning: the Dissolve Delay shouldn't be lower than {{ minDelay }} otherwise you won't get any rewards.", + "invalid-state": "The Dissolve Delay shouldn't be lower than {{ minDelay }} otherwise you won't get any rewards. The maximum delay is {{ maxDelay }}.", + "invalid-decrease": "Invalid Dissolve Delay, the value can be only increased therefore can't drop below the current value ({{ minDelay }}) and can't exceed {{ maxDelay }}." + } + } + }, "introduction-push": { "title": "Push Notifications", "heading": "You can receive push notifications if your accounts receive transactions.", From 7984fe82f7b20a8fe76e77a4ce8e7fdefb723063 Mon Sep 17 00:00:00 2001 From: Miguel Vieira Date: Tue, 9 May 2023 13:58:38 +0200 Subject: [PATCH 2/6] Feat/Shop Banner --- src/app/pages/portfolio/portfolio.html | 3 ++ src/app/pages/portfolio/portfolio.scss | 18 +++++++++ src/app/pages/portfolio/portfolio.ts | 19 ++++++++- src/app/pages/settings/settings.html | 56 ++++++++++++++++++++++++++ src/app/pages/settings/settings.ts | 8 ++++ src/assets/i18n/en.json | 17 ++++---- 6 files changed, 112 insertions(+), 9 deletions(-) diff --git a/src/app/pages/portfolio/portfolio.html b/src/app/pages/portfolio/portfolio.html index 8a0c64da0..8ca7e32b7 100644 --- a/src/app/pages/portfolio/portfolio.html +++ b/src/app/pages/portfolio/portfolio.html @@ -1,4 +1,7 @@ +
+

{{ shopBannerText }}

+
diff --git a/src/app/pages/portfolio/portfolio.scss b/src/app/pages/portfolio/portfolio.scss index 1be929a09..3b1784c59 100644 --- a/src/app/pages/portfolio/portfolio.scss +++ b/src/app/pages/portfolio/portfolio.scss @@ -56,3 +56,21 @@ ion-card { font-weight: bold; } } + +.shop-banner-wrapper { + display: flex; + align-items: center; + justify-content: center; + background-color: rgb(112, 228, 206); + padding: 6px 10px; + + cursor: pointer; + + .shop-banner-text { + color: black; + text-align: center; + font-weight: 400; + padding: 0px; + margin: 0px; + } +} diff --git a/src/app/pages/portfolio/portfolio.ts b/src/app/pages/portfolio/portfolio.ts index 66eb7daa2..98e73b833 100644 --- a/src/app/pages/portfolio/portfolio.ts +++ b/src/app/pages/portfolio/portfolio.ts @@ -13,6 +13,7 @@ import { ProtocolService } from '@airgap/angular-core' import BigNumber from 'bignumber.js' import { AirGapWallet, AirGapWalletStatus } from '@airgap/coinlib-core/wallet/AirGapWallet' import { map, take } from 'rxjs/operators' +import axios from 'axios' interface WalletGroup { mainWallet: AirGapMarketWallet @@ -39,6 +40,10 @@ export class PortfolioPage { private subscriptions: Subscription[] = [] + // Shop banner + public shopBannerText: string = '' + public shopBannerLink: string = '' + constructor( private readonly router: Router, private readonly walletsProvider: AccountProvider, @@ -62,6 +67,12 @@ export class PortfolioPage { this.calculateTotal(this.walletsProvider.getActiveWalletList()) }) this.subscriptions.push(walletChangedSub) + + const url = `https://cors-proxy.airgap.prod.gke.papers.tech/proxy?url=${encodeURI('https://airgap.it/wallet-announcement/')}` + axios.get<{ text: string, link: string }>(url).then(response => { + this.shopBannerText = response.data.text + this.shopBannerLink = response.data.link + }) } private refreshWalletGroups(wallets: AirGapMarketWallet[]) { @@ -117,7 +128,7 @@ export class PortfolioPage { the app has to be restarted or another wallet has to be added. When investigating, we saw that it is related to the transition phase. If the observable emits at the same time as the transition is happening, then this weird state occurs. If we simply wait, everything - works as intended. + works as intended. */ setTimeout(() => { this.walletGroups.next(groups) @@ -166,7 +177,7 @@ export class PortfolioPage { allWalletsSynced.pipe(take(1)).subscribe(() => { this.calculateTotal(this.walletsProvider.getActiveWalletList(), event ? event.target : null) - this.wallets.pipe(take(1)).subscribe(wallets => this.refreshWalletGroups(wallets)) + this.wallets.pipe(take(1)).subscribe((wallets) => this.refreshWalletGroups(wallets)) }) } @@ -199,4 +210,8 @@ export class PortfolioPage { } this.subscriptions = [] } + + public onClickShopBanner() { + if (this.shopBannerLink.length > 0) window.open(this.shopBannerLink, '_blank') + } } diff --git a/src/app/pages/settings/settings.html b/src/app/pages/settings/settings.html index e3d77cf78..896d5ca83 100644 --- a/src/app/pages/settings/settings.html +++ b/src/app/pages/settings/settings.html @@ -52,6 +52,62 @@ {{ 'settings.information_label' | translate }} + + + + + + + + + + {{ 'settings.airgap_website' | translate }} + + + + + + + + + + + {{ 'settings.airgap_shop' | translate }} + {{ 'settings.github_label' | translate }} diff --git a/src/app/pages/settings/settings.ts b/src/app/pages/settings/settings.ts index a85561b6d..9bfcb28ff 100644 --- a/src/app/pages/settings/settings.ts +++ b/src/app/pages/settings/settings.ts @@ -112,6 +112,14 @@ export class SettingsPage { this.browserService.openUrl('https://github.com/airgap-it') } + public airgapWebsite(): void { + this.browserService.openUrl('https://airgap.it/') + } + + public airgapShop(): void { + this.browserService.openUrl('https://shop.airgap.it/') + } + public faq(): void { this.browserService.openUrl('https://support.airgap.it') } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 60acb5edf..3e2b06a4e 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -100,6 +100,7 @@ "go_label": "Let's Go" }, "portfolio": { + "shop_banner": "Gain an extra layer of security - Get the AirGap Recovery Plate", "empty-state_text": "Start by adding coins to AirGap Wallet, you will also need the AirGap Vault application where your secret is securely stored.", "empty-state_desktop_text": "Start by adding coins to AirGap Wallet, you can either do this with the AirGap Vault application or for selected coins with a Ledger hardware wallet.", "add-coins_label": "Add Coins" @@ -142,7 +143,9 @@ "faq_label": "FAQ", "discord_label": "Join Discord", "share_label": "Share AirGap", - "information_label": "Information", + "information_label": "More", + "airgap_website": "AirGap Website", + "airgap_shop": "AirGap Shop", "github_label": "GitHub Repository", "other_label": "Other", "paste-from-clipboard_label": "Paste code from clipboard", @@ -422,9 +425,9 @@ "title": "Exchange", "exchange_label": "Exchange", "liquidity": { - "add_label": "Add Liquidity", - "remove_label": "Remove Liquidity", - "swap_label": "Swap" + "add_label": "Add Liquidity", + "remove_label": "Remove Liquidity", + "swap_label": "Swap" }, "powered-by_label": "powered by", "switch-exchange_label": "Exchange", @@ -437,7 +440,7 @@ "heading": "In order to exchange, you need at least two currencies in AirGap like Ethereum and Bitcoin.", "description": "Before you can easily swap currencies in AirGap you need to add at least two different ones.", "exchange_label": "Add Coins" - }, + }, "no-currencies-liquidity": { "heading": "To provide liquidity to the Tezos Liquidity Baking, you need both Tez and tzBTC in AirGap.", "description": "Before you can provide or remove liquidty in AirGap you need to add both Tez and tzBTC", @@ -1020,7 +1023,7 @@ "injector-url_text": "AirGap is compatible with the injector service reference implementation available on the AirGap GitHub.", "paste_label": "Paste", "include-injector_label": "Injector Service", - "include-injector_text": "Privacy preserving and usability improvement with the injectors service. Sapling transactions have to be signed only once in AirGap instead of twice with this service.", + "include-injector_text": "Privacy preserving and usability improvement with the injectors service. Sapling transactions have to be signed only once in AirGap instead of twice with this service.", "warning": { "contract-not-compatible": "The contract seems not to be compatible, you may still use it, if you're sure it'll work.", "contract-cannot-assess-compatibility": "The contract address could not be verified, you may still use it, if you're sure it'll work." @@ -1031,4 +1034,4 @@ "unknown": "Unkown error has occurred." } } -} \ No newline at end of file +} From 5cba66542c9618d53c3326348cf93ed40c85a3a8 Mon Sep 17 00:00:00 2001 From: Mike Godenzi Date: Fri, 12 May 2023 11:04:36 +0200 Subject: [PATCH 3/6] fix: fixed banner position --- src/app/pages/portfolio/portfolio.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/pages/portfolio/portfolio.scss b/src/app/pages/portfolio/portfolio.scss index 3b1784c59..6089608ef 100644 --- a/src/app/pages/portfolio/portfolio.scss +++ b/src/app/pages/portfolio/portfolio.scss @@ -63,7 +63,9 @@ ion-card { justify-content: center; background-color: rgb(112, 228, 206); padding: 6px 10px; - + margin-top: constant(safe-area-inset-top); + margin-top: env(safe-area-inset-top); + cursor: pointer; .shop-banner-text { From 9fcd43467d50bf0b97b3702773e7662e29f51ca1 Mon Sep 17 00:00:00 2001 From: Tim Schluchter Date: Fri, 12 May 2023 11:12:10 +0200 Subject: [PATCH 4/6] Feat/price per unit balance 0 --- .../portfolio-item/portfolio-item.html | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/app/components/portfolio-item/portfolio-item.html b/src/app/components/portfolio-item/portfolio-item.html index 7f3e0582e..cf141d8b5 100644 --- a/src/app/components/portfolio-item/portfolio-item.html +++ b/src/app/components/portfolio-item/portfolio-item.html @@ -1,8 +1,17 @@ - - + +

- +

@@ -37,7 +46,7 @@

+

@@ -46,25 +55,25 @@

- ${{ balance | cryptoToFiat: { protocolIdentifier: wallet.protocol.identifier, currentMarketPrice: - marketPrice } | async | number: '1.2-2' }} + ${{ balance | cryptoToFiat: { protocolIdentifier: wallet.protocol.identifier, currentMarketPrice: marketPrice } | async | number: + '1.2-2' }}

- +

- + ${{ marketPrice.toNumber() | number: '1.2-4' }}

- +

@@ -87,18 +96,18 @@

- +

- +

- +

- +

From 047c61d3b8c0ea858436a7e66bffbce1a6fdb8d0 Mon Sep 17 00:00:00 2001 From: Miguel Vieira Date: Mon, 15 May 2023 15:16:57 +0200 Subject: [PATCH 5/6] Feat/ Mt Pelerin --- package-lock.json | 28 ++++----- package.json | 4 +- src/app/app-routing.module.ts | 7 ++- src/app/app.component.ts | 15 +++-- .../account-transaction-list.html | 25 ++++++++ .../account-transaction-list.scss | 18 ++++++ .../account-transaction-list.ts | 46 ++++++++++++-- src/app/pages/settings/settings.html | 10 +++ src/app/pages/settings/settings.ts | 4 ++ .../trading-settings.module.ts | 23 +++++++ .../trading-settings.page.html | 63 +++++++++++++++++++ .../trading-settings.page.scss | 45 +++++++++++++ .../trading-settings/trading-settings.page.ts | 28 +++++++++ src/assets/i18n/en.json | 19 +++++- 14 files changed, 307 insertions(+), 28 deletions(-) create mode 100644 src/app/pages/trading-settings/trading-settings.module.ts create mode 100644 src/app/pages/trading-settings/trading-settings.page.html create mode 100644 src/app/pages/trading-settings/trading-settings.page.scss create mode 100644 src/app/pages/trading-settings/trading-settings.page.ts diff --git a/package-lock.json b/package-lock.json index dc224386e..9697f4a34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,8 @@ "hasInstallScript": true, "dependencies": { "@airgap/aeternity": "0.13.15-beta.10", - "@airgap/angular-core": "0.0.37-beta.17", - "@airgap/angular-ngrx": "0.0.37-beta.17", + "@airgap/angular-core": "0.0.37-beta.21", + "@airgap/angular-ngrx": "0.0.37-beta.21", "@airgap/astar": "0.13.15-beta.10", "@airgap/beacon-sdk": "3.1.5-beta.0", "@airgap/bitcoin": "0.13.15-beta.10", @@ -173,9 +173,9 @@ } }, "node_modules/@airgap/angular-core": { - "version": "0.0.37-beta.17", - "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.37-beta.17.tgz", - "integrity": "sha512-7Sadka8upZcZTnDUGzVo+08sQanPTMZGfQXhm8uF3x8+89OGQcfXx0k8q8EBV+eMCyivOg8EjlfwVEQjvYSpTw==", + "version": "0.0.37-beta.21", + "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.37-beta.21.tgz", + "integrity": "sha512-QVCsL6wGyqwuXwfSnpiI25PHDTbMRavdOPV2+i6KPJw/4/rV5q/hRs/mnyKQX8N2OFHGYOW4x/TBjS3ygc3hpA==", "dependencies": { "tslib": "^2.2.0" }, @@ -237,9 +237,9 @@ } }, "node_modules/@airgap/angular-ngrx": { - "version": "0.0.37-beta.17", - "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.37-beta.17.tgz", - "integrity": "sha512-swQ55n5qJ0r4i6IirciGg4YfBa/75vbTlyRMTO01cSgvBBSD4PWjyg5bhyr1WkQRwc80rh1PG7d0pljXm4L8+w==", + "version": "0.0.37-beta.21", + "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.37-beta.21.tgz", + "integrity": "sha512-86E0IFCrCT/LAZccfj7K56tyEVnek5JUJsSTei/TL0CIJ5Zmy6pKPgdOEPUkQWka+rk1Zg/jYsWkeG2ESIwolQ==", "dependencies": { "tslib": "^2.2.0" }, @@ -26527,17 +26527,17 @@ } }, "@airgap/angular-core": { - "version": "0.0.37-beta.17", - "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.37-beta.17.tgz", - "integrity": "sha512-7Sadka8upZcZTnDUGzVo+08sQanPTMZGfQXhm8uF3x8+89OGQcfXx0k8q8EBV+eMCyivOg8EjlfwVEQjvYSpTw==", + "version": "0.0.37-beta.21", + "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.37-beta.21.tgz", + "integrity": "sha512-QVCsL6wGyqwuXwfSnpiI25PHDTbMRavdOPV2+i6KPJw/4/rV5q/hRs/mnyKQX8N2OFHGYOW4x/TBjS3ygc3hpA==", "requires": { "tslib": "^2.2.0" } }, "@airgap/angular-ngrx": { - "version": "0.0.37-beta.17", - "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.37-beta.17.tgz", - "integrity": "sha512-swQ55n5qJ0r4i6IirciGg4YfBa/75vbTlyRMTO01cSgvBBSD4PWjyg5bhyr1WkQRwc80rh1PG7d0pljXm4L8+w==", + "version": "0.0.37-beta.21", + "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.37-beta.21.tgz", + "integrity": "sha512-86E0IFCrCT/LAZccfj7K56tyEVnek5JUJsSTei/TL0CIJ5Zmy6pKPgdOEPUkQWka+rk1Zg/jYsWkeG2ESIwolQ==", "requires": { "tslib": "^2.2.0" } diff --git a/package.json b/package.json index 648c56428..6acb8f54b 100644 --- a/package.json +++ b/package.json @@ -56,8 +56,8 @@ }, "dependencies": { "@airgap/aeternity": "0.13.15-beta.10", - "@airgap/angular-core": "0.0.37-beta.17", - "@airgap/angular-ngrx": "0.0.37-beta.17", + "@airgap/angular-core": "0.0.37-beta.21", + "@airgap/angular-ngrx": "0.0.37-beta.21", "@airgap/astar": "0.13.15-beta.10", "@airgap/beacon-sdk": "3.1.5-beta.0", "@airgap/bitcoin": "0.13.15-beta.10", diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index bb81e8e5c..008433d5f 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -85,7 +85,8 @@ const routes: Routes = [ special: DataResolverService }, canActivate: [ProtocolGuard, ServiceKeyGuard], - loadChildren: () => import('./pages/sub-account-add-generic/sub-account-add-generic.module').then((m) => m.SubAccountAddGenericPageModule) + loadChildren: () => + import('./pages/sub-account-add-generic/sub-account-add-generic.module').then((m) => m.SubAccountAddGenericPageModule) }, { path: 'sub-account-select/:id', @@ -225,6 +226,10 @@ const routes: Routes = [ (m) => m.InteractionSelectionSettingsPageModule ) }, + { + path: 'trading-settings', + loadChildren: () => import('./pages/trading-settings/trading-settings.module').then((m) => m.TradingSettingsPageModule) + }, { path: 'collectibles-list/:id/:publicKey/:protocolID/:addressIndex', resolve: { diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 53bc67650..96a89a837 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -21,10 +21,7 @@ import { MainProtocolSymbols, NetworkType } from '@airgap/coinlib-core' -import { - generateId, - IACMessageType -} from '@airgap/serializer' +import { generateId, IACMessageType } from '@airgap/serializer' import { TezosProtocolNetwork, TezosBlockExplorer, @@ -66,6 +63,7 @@ import { WalletStorageKey, WalletStorageService } from './services/storage/stora import { WalletconnectService } from './services/walletconnect/walletconnect.service' import { faProtocolSymbol } from './types/GenericProtocolSymbols' import { generateGUID } from './utils/utils' +import { HttpClient } from '@angular/common/http' @Component({ selector: 'app-root', @@ -96,6 +94,7 @@ export class AppComponent implements AfterViewInit { private readonly themeService: ThemeService, private readonly navigationService: NavigationService, private readonly isolatedModulesService: IsolatedModulesService, + private readonly http: HttpClient, @Inject(APP_PLUGIN) private readonly app: AppPlugin, @Inject(APP_INFO_PLUGIN) private readonly appInfo: AppInfoPlugin, @Inject(SPLASH_SCREEN_PLUGIN) private readonly splashScreen: SplashScreenPlugin @@ -143,6 +142,14 @@ export class AppComponent implements AfterViewInit { }) } + // Mt Perelin + this.http + .get('https://api.mtpelerin.com/currencies/tokens') + .toPromise() + .then((result) => { + this.storageProvider.setCache('mtperelin-currencies', result) + }) + this.appSerivce.setReady() } diff --git a/src/app/pages/account-transaction-list/account-transaction-list.html b/src/app/pages/account-transaction-list/account-transaction-list.html index 2a3aae47b..1c1f6fb5a 100644 --- a/src/app/pages/account-transaction-list/account-transaction-list.html +++ b/src/app/pages/account-transaction-list/account-transaction-list.html @@ -109,6 +109,31 @@ + + + + + {{ 'swap.buy_label' | translate }} +
+ {{ 'account-transaction-list.provided_by' | translate }} + +
+
+
+
+ + + + {{ 'swap.sell_label' | translate }} +
+ {{ 'account-transaction-list.provided_by' | translate }} + +
+
+
+
+
+ diff --git a/src/app/pages/account-transaction-list/account-transaction-list.scss b/src/app/pages/account-transaction-list/account-transaction-list.scss index 0a074f435..e7509c6af 100644 --- a/src/app/pages/account-transaction-list/account-transaction-list.scss +++ b/src/app/pages/account-transaction-list/account-transaction-list.scss @@ -27,3 +27,21 @@ ion-fab { svg { stroke: none; } + +.mt-perelin-button { + border: 1px solid gray; + border-radius: 100px; + + div { + display: flex; + align-items: center; + gap: 8px; + margin-left: auto; + font-size: 12px; + color: rgb(83, 83, 83); + + img { + height: 18px; + } + } +} diff --git a/src/app/pages/account-transaction-list/account-transaction-list.ts b/src/app/pages/account-transaction-list/account-transaction-list.ts index f47f4a93e..f855dfab0 100644 --- a/src/app/pages/account-transaction-list/account-transaction-list.ts +++ b/src/app/pages/account-transaction-list/account-transaction-list.ts @@ -1,9 +1,9 @@ -import { ProtocolService } from '@airgap/angular-core' +import { InternalStorageKey, InternalStorageService, ProtocolService } from '@airgap/angular-core' import { AirGapMarketWallet, IAirGapTransaction, MainProtocolSymbols, - SubProtocolSymbols, + SubProtocolSymbols } from '@airgap/coinlib-core' import { Action } from '@airgap/coinlib-core/actions/Action' import { IAirGapTransactionResult, IProtocolTransactionCursor } from '@airgap/coinlib-core/interfaces/IAirGapTransaction' @@ -96,6 +96,9 @@ export class AccountTransactionListPage { private protocolID: string private addressIndex + // Mt Perelin + public isMtPerelinActive: boolean = false + constructor( public readonly alertCtrl: AlertController, public readonly navController: NavController, @@ -116,7 +119,8 @@ export class AccountTransactionListPage { private readonly pushBackendProvider: PushBackendProvider, private readonly exchangeProvider: ExchangeProvider, private readonly extensionsService: ExtensionsService, - private readonly browserService: BrowserService + private readonly browserService: BrowserService, + private readonly storageService: InternalStorageService ) { this.isDesktop = this.platform.is('desktop') @@ -162,6 +166,18 @@ export class AccountTransactionListPage { this.actionGroup.getActions().then((actions) => { this.actions = actions }) + + // Mt Perelin + this.storageService.get(InternalStorageKey.SETTINGS_TRADING_USE_MTPELERIN).then((active) => { + if (active) { + this.storageProvider.getCache('mtperelin-currencies').then((savedCurrencies) => { + this.wallet.protocol.getSymbol().then((symbol) => { + const validCurrency = Object.values(savedCurrencies).find((currency) => currency.symbol === symbol) + this.isMtPerelinActive = !!active && !!validCurrency + }) + }) + } + }) } public showNoTransactionScreen(): boolean { @@ -268,8 +284,10 @@ export class AccountTransactionListPage { public async loadInitialTransactions(forceRefresh: boolean = false): Promise { if (forceRefresh || this.transactions.length === 0) { this.transactions = - (await this.storageProvider.getCache(await this.accountProvider.getAccountIdentifier(this.wallet)))?.slice(0, 10) ?? - [] + (await this.storageProvider.getCache(await this.accountProvider.getAccountIdentifier(this.wallet)))?.slice( + 0, + 10 + ) ?? [] } const transactionPromise: Promise = this.getTransactions(undefined, this.TRANSACTION_LIMIT) @@ -314,7 +332,10 @@ export class AccountTransactionListPage { }) } - await this.storageProvider.setCache(await this.accountProvider.getAccountIdentifier(this.wallet), this.transactions) + await this.storageProvider.setCache( + await this.accountProvider.getAccountIdentifier(this.wallet), + this.transactions + ) this.txOffset = this.transactions.length this.infiniteEnabled = this.transactions.length >= this.TRANSACTION_LIMIT @@ -402,4 +423,17 @@ export class AccountTransactionListPage { this.subscription.unsubscribe() this.walletChanged.unsubscribe() } + + // Mt Perelin + public async buyMtPerelin() { + this.wallet.protocol.getSymbol().then((symbol) => { + window.open(`https://buy.mtpelerin.com/?type=direct-link&bdc=${symbol}&addr=${this.wallet.addresses[0]}&rfr=bcH4RmHm`, '_blank') + }) + } + + public async sellMtPerelin() { + this.wallet.protocol.getSymbol().then((symbol) => { + window.open(`https://sell.mtpelerin.com/?type=direct-link&tab=sell&ssc=${symbol}&rfr=bcH4RmHm`, '_blank') + }) + } } diff --git a/src/app/pages/settings/settings.html b/src/app/pages/settings/settings.html index 896d5ca83..d8fe036e4 100644 --- a/src/app/pages/settings/settings.html +++ b/src/app/pages/settings/settings.html @@ -162,5 +162,15 @@ {{ 'settings.qr-advanced-settings_label' | translate }} + + + + {{ 'settings.trading_settings.label' | translate }} + + + + {{ 'settings.trading_settings.text' | translate }} + + diff --git a/src/app/pages/settings/settings.ts b/src/app/pages/settings/settings.ts index 9bfcb28ff..bfd855b75 100644 --- a/src/app/pages/settings/settings.ts +++ b/src/app/pages/settings/settings.ts @@ -140,6 +140,10 @@ export class SettingsPage { this.navigate('/interaction-selection-settings') } + public goToTradingSettings(): void { + this.navigate('/trading-settings') + } + private navigate(url: string) { this.router.navigateByUrl(url).catch(handleErrorSentry(ErrorCategory.NAVIGATION)) } diff --git a/src/app/pages/trading-settings/trading-settings.module.ts b/src/app/pages/trading-settings/trading-settings.module.ts new file mode 100644 index 000000000..236d70d14 --- /dev/null +++ b/src/app/pages/trading-settings/trading-settings.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from '@angular/core' +import { CommonModule } from '@angular/common' +import { FormsModule } from '@angular/forms' + +import { IonicModule } from '@ionic/angular' + +import { TradingSettingsPage } from './trading-settings.page' +import { TranslateModule } from '@ngx-translate/core' +import { ComponentsModule } from '@airgap/angular-core' +import { RouterModule } from '@angular/router' + +@NgModule({ + imports: [ + CommonModule, + FormsModule, + IonicModule, + ComponentsModule, + TranslateModule, + RouterModule.forChild([{ path: '', component: TradingSettingsPage }]) + ], + declarations: [TradingSettingsPage] +}) +export class TradingSettingsPageModule {} diff --git a/src/app/pages/trading-settings/trading-settings.page.html b/src/app/pages/trading-settings/trading-settings.page.html new file mode 100644 index 000000000..0cf7f15aa --- /dev/null +++ b/src/app/pages/trading-settings/trading-settings.page.html @@ -0,0 +1,63 @@ + + + + + + + {{ 'settings.trading_settings.text' | translate }} + + + + + + {{ 'settings.trading_settings.mtpelerin' | translate }} + + + +
+ +

{{ 'mtpelerin.header1' | translate }}

+

+ {{ 'mtpelerin.paragraph1' | translate }} +

+

{{ 'mtpelerin.header2' | translate }}

+
    +
  • {{ 'mtpelerin.lineItem1' | translate }}
  • +
  • {{ 'mtpelerin.lineItem2' | translate }}
  • +
  • {{ 'mtpelerin.lineItem3' | translate }}
  • +
+ + + + + {{ 'mtpelerin.button1' | translate }} + + + + + + + {{ 'mtpelerin.button2' | translate }} + + + + + + {{ 'mtpelerin.note' | translate }} + +
+
diff --git a/src/app/pages/trading-settings/trading-settings.page.scss b/src/app/pages/trading-settings/trading-settings.page.scss new file mode 100644 index 000000000..ccd470568 --- /dev/null +++ b/src/app/pages/trading-settings/trading-settings.page.scss @@ -0,0 +1,45 @@ +.mtpelerin-wrapper { + display: flex; + flex-direction: column; + padding: 24px; + + .buttons-wrapper { + display: flex; + flex-direction: column; + } + + img { + height: 48px; + width: fit-content; + } + + h3 { + color: white; + margin-top: 32px; + margin-bottom: 0px; + font-size: 18px; + font-weight: bold; + } + + p { + margin-top: 12px; + margin-bottom: 0px; + font-size: 14px; + font-weight: 400; + } + + ul { + margin-top: 12px; + margin-bottom: 32px; + font-size: 14px; + font-weight: 400; + } + + span { + margin-top: 12px; + margin-bottom: 0px; + font-size: 12px; + font-weight: 400; + color: gray; + } +} diff --git a/src/app/pages/trading-settings/trading-settings.page.ts b/src/app/pages/trading-settings/trading-settings.page.ts new file mode 100644 index 000000000..926814893 --- /dev/null +++ b/src/app/pages/trading-settings/trading-settings.page.ts @@ -0,0 +1,28 @@ +import { InternalStorageKey, InternalStorageService } from '@airgap/angular-core' +import { Component, OnInit } from '@angular/core' + +@Component({ + selector: 'app-trading-settings', + templateUrl: './trading-settings.page.html', + styleUrls: ['./trading-settings.page.scss'] +}) +export class TradingSettingsPage implements OnInit { + public useMtPerelin: boolean = false + + constructor(private readonly storageService: InternalStorageService) { + this.storageService.get(InternalStorageKey.SETTINGS_TRADING_USE_MTPELERIN).then((value) => { + this.useMtPerelin = value + }) + } + + ngOnInit() {} + + public async toggleUseMtPerelin(event: any) { + const value = event.detail.checked + await this.storageService.set(InternalStorageKey.SETTINGS_TRADING_USE_MTPELERIN, value) + } + + public navigate(path: string) { + window.open(path, '_blank') + } +} diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 3e2b06a4e..cae48387b 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -44,7 +44,8 @@ "cancel": "Cancel", "confirm": "Migrate" }, - "no-transactions_text": "There are no transactions yet for this account." + "no-transactions_text": "There are no transactions yet for this account.", + "provided_by": "Provided by" }, "account-transaction-detail": { "available_label": "Available", @@ -177,8 +178,24 @@ "interaction": { "label": "Interaction Setting", "text": "Vault and Wallet Interaction Settings" + }, + "trading_settings": { + "label": "Trading", + "text": "Advanced Trading Settings", + "mtpelerin": "Use Mt Pelerin" } }, + "mtpelerin": { + "header1": "Buy & sell crypto with Mt Pelerin – The Swiss gateway to the crypto world", + "paragraph1": "Invest in Bitcoin, Ether and the most popular assets on multiple chains in a few clicks, at the best prices on the market and no KYC required. Withdraw them at any time in 14 currencies back on your bank account in 171 countries.", + "header2": "Simple and transparent", + "lineItem1": "No identification required", + "lineItem2": "Live, transparent exchange rate", + "lineItem3": "Make a payment, get crypto directly on AirGap", + "button1": "Learn more about buying", + "button2": "Learn more about selling", + "note": "Note – Mt. Pelerin accepts clients from all countries, except US and Russian persons, and residents of: Afghanistan, Belarus, Burundi, Central African Republic, Cuba, Democratic Republic of the Congo, Guinea, Guinea-Bissau, Iran, Iraq, Lebanon, Libya, Mainland China (Hong Kong and Taiwan accepted), Mali, Myanmar, Nicaragua, North Korea, Russia, Somalia, Sudan, South Sudan, Syria, Venezuela, Yemen, Zimbabwe." + }, "qr-settings-page": { "title": "QR Settings" }, From b38f2dc1eaf199052898152a5a3bd4edffb3d238 Mon Sep 17 00:00:00 2001 From: Mike Godenzi Date: Tue, 16 May 2023 09:16:41 +0200 Subject: [PATCH 6/6] chore: updated dependencies --- package-lock.json | 304 +++++++++++++++++++++++----------------------- package.json | 38 +++--- 2 files changed, 171 insertions(+), 171 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9697f4a34..b27515cbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,27 +9,27 @@ "version": "0.0.1", "hasInstallScript": true, "dependencies": { - "@airgap/aeternity": "0.13.15-beta.10", - "@airgap/angular-core": "0.0.37-beta.21", - "@airgap/angular-ngrx": "0.0.37-beta.21", - "@airgap/astar": "0.13.15-beta.10", + "@airgap/aeternity": "0.13.15", + "@airgap/angular-core": "0.0.37", + "@airgap/angular-ngrx": "0.0.37", + "@airgap/astar": "0.13.15", "@airgap/beacon-sdk": "3.1.5-beta.0", - "@airgap/bitcoin": "0.13.15-beta.10", - "@airgap/coinlib-core": "0.13.15-beta.10", - "@airgap/coreum": "0.13.15-beta.10", - "@airgap/cosmos": "0.13.15-beta.10", - "@airgap/cosmos-core": "0.13.15-beta.10", - "@airgap/crypto": "0.13.15-beta.10", - "@airgap/ethereum": "0.13.15-beta.10", - "@airgap/groestlcoin": "0.13.15-beta.10", - "@airgap/icp": "0.13.15-beta.10", - "@airgap/module-kit": "0.13.15-beta.10", - "@airgap/moonbeam": "0.13.15-beta.10", - "@airgap/polkadot": "0.13.15-beta.10", + "@airgap/bitcoin": "0.13.15", + "@airgap/coinlib-core": "0.13.15", + "@airgap/coreum": "0.13.15", + "@airgap/cosmos": "0.13.15", + "@airgap/cosmos-core": "0.13.15", + "@airgap/crypto": "0.13.15", + "@airgap/ethereum": "0.13.15", + "@airgap/groestlcoin": "0.13.15", + "@airgap/icp": "0.13.15", + "@airgap/module-kit": "0.13.15", + "@airgap/moonbeam": "0.13.15", + "@airgap/polkadot": "0.13.15", "@airgap/sapling-wasm": "0.0.7", - "@airgap/serializer": "0.13.15-beta.10", - "@airgap/substrate": "0.13.15-beta.10", - "@airgap/tezos": "0.13.15-beta.10", + "@airgap/serializer": "0.13.15", + "@airgap/substrate": "0.13.15", + "@airgap/tezos": "0.13.15", "@angular/animations": "^11.2.9", "@angular/common": "^11.2.9", "@angular/core": "^11.2.9", @@ -162,9 +162,9 @@ } }, "node_modules/@airgap/aeternity": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/aeternity/-/aeternity-0.13.15-beta.10.tgz", - "integrity": "sha512-Yi19sQMqQwZJ20fCbPUfpkLDBZLu7RangN8bePQotPaV45rZt45FplxNC+iCRdbAGbSUdWPhTeLzn+USXoA8TA==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/aeternity/-/aeternity-0.13.15.tgz", + "integrity": "sha512-Ooj8XFJZbK0v5tZHsX05yPMQGEVO2KfgycBx3H4asd6TqOiEaj9fE9ZVZia+v/uObHMgo3pWkuRZqfeuLBR4FQ==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -173,30 +173,30 @@ } }, "node_modules/@airgap/angular-core": { - "version": "0.0.37-beta.21", - "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.37-beta.21.tgz", - "integrity": "sha512-QVCsL6wGyqwuXwfSnpiI25PHDTbMRavdOPV2+i6KPJw/4/rV5q/hRs/mnyKQX8N2OFHGYOW4x/TBjS3ygc3hpA==", + "version": "0.0.37", + "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.37.tgz", + "integrity": "sha512-21TmmLmU+31/X/TyNj9pn71KQIJY1jzwDI5dWkYgSw7UjciYs+ch6muBGwK9fZyhoCBqnaQv98jBn+WSvGGV3w==", "dependencies": { "tslib": "^2.2.0" }, "peerDependencies": { - "@airgap/aeternity": "^0.13.15-beta.10", - "@airgap/astar": "^0.13.15-beta.10", - "@airgap/bitcoin": "^0.13.15-beta.10", - "@airgap/coinlib-core": "^0.13.15-beta.10", - "@airgap/coreum": "^0.13.15-beta.10", - "@airgap/cosmos": "^0.13.15-beta.10", - "@airgap/cosmos-core": "^0.13.15-beta.10", - "@airgap/crypto": "^0.13.15-beta.10", - "@airgap/ethereum": "^0.13.15-beta.10", - "@airgap/groestlcoin": "^0.13.15-beta.10", - "@airgap/icp": "^0.13.15-beta.10", - "@airgap/module-kit": "^0.13.15-beta.10", - "@airgap/moonbeam": "^0.13.15-beta.10", - "@airgap/polkadot": "^0.13.15-beta.10", - "@airgap/serializer": "^0.13.15-beta.10", - "@airgap/substrate": "^0.13.15-beta.10", - "@airgap/tezos": "^0.13.15-beta.10", + "@airgap/aeternity": "^0.13.15", + "@airgap/astar": "^0.13.15", + "@airgap/bitcoin": "^0.13.15", + "@airgap/coinlib-core": "^0.13.15", + "@airgap/coreum": "^0.13.15", + "@airgap/cosmos": "^0.13.15", + "@airgap/cosmos-core": "^0.13.15", + "@airgap/crypto": "^0.13.15", + "@airgap/ethereum": "^0.13.15", + "@airgap/groestlcoin": "^0.13.15", + "@airgap/icp": "^0.13.15", + "@airgap/module-kit": "^0.13.15", + "@airgap/moonbeam": "^0.13.15", + "@airgap/polkadot": "^0.13.15", + "@airgap/serializer": "^0.13.15", + "@airgap/substrate": "^0.13.15", + "@airgap/tezos": "^0.13.15", "@angular/animations": "^11.2.9", "@angular/common": "^11.2.9", "@angular/core": "^11.2.9", @@ -237,15 +237,15 @@ } }, "node_modules/@airgap/angular-ngrx": { - "version": "0.0.37-beta.21", - "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.37-beta.21.tgz", - "integrity": "sha512-86E0IFCrCT/LAZccfj7K56tyEVnek5JUJsSTei/TL0CIJ5Zmy6pKPgdOEPUkQWka+rk1Zg/jYsWkeG2ESIwolQ==", + "version": "0.0.37", + "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.37.tgz", + "integrity": "sha512-eOWmX8O+WCyIvZrrAcDmasZivDIafhP9MITWxQVylHN8TblLCpJpXhD2LzN/qz+5389t4/O3lH/95htBwznM8w==", "dependencies": { "tslib": "^2.2.0" }, "peerDependencies": { - "@airgap/angular-core": "^0.0.36", - "@airgap/coinlib-core": "^0.13.15-beta.10", + "@airgap/angular-core": "^0.0.37", + "@airgap/coinlib-core": "^0.13.15", "@angular/common": "^11.2.9", "@angular/core": "^11.2.9", "@angular/platform-browser": "^11.2.9", @@ -259,9 +259,9 @@ } }, "node_modules/@airgap/astar": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/astar/-/astar-0.13.15-beta.10.tgz", - "integrity": "sha512-Sn/3Gaun9m5JqMpmiNx9fKXsdOTuzShkoYmtEV7Y00OdmExHQR3Dojfy2M/DJ1kjjVj4gT5COELFk/T/+tsp2g==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/astar/-/astar-0.13.15.tgz", + "integrity": "sha512-19KOTmpEdjrKoE6TNlv1Ba32bmFqTwjJCdHdx/cmtDETU5eKRMEwd5ZtQddgnbv5b3E0oYeePUoTdiMPg0Ucmg==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -410,9 +410,9 @@ } }, "node_modules/@airgap/bitcoin": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/bitcoin/-/bitcoin-0.13.15-beta.10.tgz", - "integrity": "sha512-G/vStubCH9DtSIqQ3Mh/loUBSMrfL+s+SJPPLIWUb4YKqXNS272jE1XqW6MTsfv9BTt40P9ZD1Nw8NLYwDvgQQ==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/bitcoin/-/bitcoin-0.13.15.tgz", + "integrity": "sha512-UXS25+x+XEw0HMTDEPJSCPlvdc9jSzv5vCnHdUUq8gcT/rvy5KmZPEqfGCL4XwZ5wrtclZhTS0BEvQ2s4EhJ7g==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -422,9 +422,9 @@ } }, "node_modules/@airgap/coinlib-core": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/coinlib-core/-/coinlib-core-0.13.15-beta.10.tgz", - "integrity": "sha512-icwj44ScCimoBHZR8DBdOFg2bzlab8nk8K2DGlMfCPhMO8xq+huA9RFp9qqOGo4++sGc+kQDJGihyTugSmw0Lg==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/coinlib-core/-/coinlib-core-0.13.15.tgz", + "integrity": "sha512-JIxBZFanbjJ+WUYlhdgbnNRnHfE40FzVl7rkg6OYD8rJ0bH86GdmCYN7/U93r5mRy3HQ9CrRCREm/c4h0Ois3Q==", "dependencies": { "@stablelib/blake2b": "^1.0.1", "@stablelib/bytes": "^1.0.1", @@ -436,9 +436,9 @@ } }, "node_modules/@airgap/coreum": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/coreum/-/coreum-0.13.15-beta.10.tgz", - "integrity": "sha512-BL8nCoEDU+ysJSF7rFX3CWNE0JQcBK3iIYsV7ZTayZ2/fMBP0E/rAoUoFye/nh7BRP0USj050jI9nyzJVqcG2Q==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/coreum/-/coreum-0.13.15.tgz", + "integrity": "sha512-KH4HPZ4I/CkiEj2uRvpVaGnk5TVLOq4k3IuNgkawq/py2RVmHlXzMUboY/PlT6/Uqtx3L+kYfJasA4V07byvNg==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/cosmos-core": "*", @@ -448,9 +448,9 @@ } }, "node_modules/@airgap/cosmos": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/cosmos/-/cosmos-0.13.15-beta.10.tgz", - "integrity": "sha512-TA4OaMh08jgDuUgOggB2cUqvUOCRK5uoNYf2VCsFtgCucGUkIQ3BeDi7n7PhxpF9cdcMb/S/PDkEh/mz3dtX5g==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/cosmos/-/cosmos-0.13.15.tgz", + "integrity": "sha512-fyUeMwJvNzlCQgdNT6kA9YG2S8daFN5nvG5RI2EojCs5esWBetD13wvyX4zXSf1riMpq1KpgKQLzqfXsifYxlw==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/cosmos-core": "*", @@ -460,9 +460,9 @@ } }, "node_modules/@airgap/cosmos-core": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/cosmos-core/-/cosmos-core-0.13.15-beta.10.tgz", - "integrity": "sha512-jID1O5Tpuydrt6wibsM1ergRHDUQ1GdSEcHHc9W7B6EZZL+9HS0j1Ehx+8naMwqrNkvqaM4wOCVI9hr2bX9b8g==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/cosmos-core/-/cosmos-core-0.13.15.tgz", + "integrity": "sha512-ptyfJS/rVcP/auipoMfhbCGTpciTlUUKnN+MwIuwNC5SUSCwXkOQYV+t+5fcPbQ3X7tCfjj5QRWi2ZSKWrL0DA==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -471,9 +471,9 @@ } }, "node_modules/@airgap/crypto": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/crypto/-/crypto-0.13.15-beta.10.tgz", - "integrity": "sha512-PU8+3UGxYfpToAgodUAiex7zfLAdcAz+WMgxFYGcJQ/E9pOJq7t8Nc12b3dOAlIpoGtj3iqlN0AR7rf/BfG50A==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/crypto/-/crypto-0.13.15.tgz", + "integrity": "sha512-CLizaNFFfu7RhmT7wyhhw2D07DuUH6zzmzn5cSYAJlmmhlOTFWbwxHGDUWOonEzINmzrmZFgnZ4tmpANVzeMgg==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -488,9 +488,9 @@ "integrity": "sha512-rJjV7JIDxoardnZMgk4Uor5Z6OVsAE4I5uDlkGAb0tQ5NN0gmz9Bu2LKMPSCv7UqDpZowDX4BbMDuSqdO/IsbQ==" }, "node_modules/@airgap/ethereum": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/ethereum/-/ethereum-0.13.15-beta.10.tgz", - "integrity": "sha512-zDZVrI53bzXCP5LOk7dojrxXkqcNFxHd0gCGiwiMKJb2h45qf27FLZMuCI8WzyfPtAo1tZhxzVqCAWt8hRYUCg==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/ethereum/-/ethereum-0.13.15.tgz", + "integrity": "sha512-vsF5S1HbOZWYR70/I79T7y32A7NJzvh8oLNZYUmdYwvIiZs3YzsyUO45UTpIytv3EAf6peDA9wUSUhOm6zwyiA==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -502,9 +502,9 @@ } }, "node_modules/@airgap/groestlcoin": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/groestlcoin/-/groestlcoin-0.13.15-beta.10.tgz", - "integrity": "sha512-uTzPud+ti2SCHmGzxU57dmpC5Msn+pDffDf++Xt05XSUMmCqDVAW/7RuJHoFxPxdYq7WFBmw+Slard5/1qPIiw==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/groestlcoin/-/groestlcoin-0.13.15.tgz", + "integrity": "sha512-btt20YQh1rVHcfixTlHqfMK0v33j82y/l296FASMukQLY2rlK00u4IaGvo6b3QmcjZsgLZ+W8c2lNOtIMWlG1Q==", "dependencies": { "@airgap/bitcoin": "*", "@airgap/coinlib-core": "*", @@ -513,9 +513,9 @@ } }, "node_modules/@airgap/icp": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/icp/-/icp-0.13.15-beta.10.tgz", - "integrity": "sha512-rB9u5YuTKrUzVrmE9wcgbDkyFJwric2hlEiENy42fYbj64IB++GCkjyUiC5kXLKl5sjQkOBIW7z7mT7B02avBg==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/icp/-/icp-0.13.15.tgz", + "integrity": "sha512-Ku/6Oxlg9DXjKZhbov4ypwQkNpA8SIIk0CVcvA7yPxbumApa+l4svEXMX14nLJ6xF86oKrtW6EMOqOg3wH9Z+g==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -579,18 +579,18 @@ } }, "node_modules/@airgap/module-kit": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/module-kit/-/module-kit-0.13.15-beta.10.tgz", - "integrity": "sha512-nYJkKvf8+tS6Q2Lt7THnEDtBtg1omKwuzEcHtavShWyugTqhmmMcGBKVwrMOI0gNdxfC4ap+BxFDCdrOZXq/ZA==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/module-kit/-/module-kit-0.13.15.tgz", + "integrity": "sha512-n2hxPTWpvtJcTL8MRWQNkj0Su9ovg5d43i8H+YaWzcNnFt1Fl2FidmIS3F+JGntqfMQgzTCQnNylI+kWV4zjsg==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/serializer": "*" } }, "node_modules/@airgap/moonbeam": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/moonbeam/-/moonbeam-0.13.15-beta.10.tgz", - "integrity": "sha512-CahZ8Gv+m684KBcjJrHyXdCWsVbFvZUXRcNnIYyR3Iey2OpxTiWZWPKl8FVsq4zl/UeXPB3iZGfOkf/5E5/D0g==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/moonbeam/-/moonbeam-0.13.15.tgz", + "integrity": "sha512-29BbL6tsi7Fl6M9ks1eqjlbTNrCf92v14nlWkYxJ0O/EDMkAOe7OLRLDlch0+5viltsHRKtUe1xJ6HgFojfVXQ==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -599,9 +599,9 @@ } }, "node_modules/@airgap/polkadot": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/polkadot/-/polkadot-0.13.15-beta.10.tgz", - "integrity": "sha512-lqDlSx1GfyA9Xsi1UrDfcJkFuWuDeiNqTS6HLokCfR+PO/g3HawKEg3bINtLnv2uAKvclKx8iylbDq+oxZamxA==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/polkadot/-/polkadot-0.13.15.tgz", + "integrity": "sha512-QbY0R0r0eABbfFn75shR3cHYP/15yPjNOSweBp0r9gCuVa9azClg0j3CPxH8jMCZqTDIuzrZRKrGpWPwMAAoTg==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -614,17 +614,17 @@ "integrity": "sha512-IMODbGPTBYKuO5ztiHX9C1PTlhqZvmVWv7m7zj5+VMcbBxrk4+jBAf7FYTH5l+IUsNMaHBOuh8Qq3A1b/pm7jQ==" }, "node_modules/@airgap/serializer": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/serializer/-/serializer-0.13.15-beta.10.tgz", - "integrity": "sha512-woa1UG/UJQxlLuAxWpxxbHdIyPDGzNiEbdmBMe7HGi0IMnT+4SRqhQcLGBUSoPG4zB2hy00U4eICNGGaJDqhLg==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/serializer/-/serializer-0.13.15.tgz", + "integrity": "sha512-5vOthazh7KFYpRO2i9lZI/D5LOCGxOvaTYIIv+b4DZxgKcOzOinnL/+t2HS8L1H1MF3fIdy90yJBYwnVyMKq2w==", "dependencies": { "@airgap/coinlib-core": "*" } }, "node_modules/@airgap/substrate": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/substrate/-/substrate-0.13.15-beta.10.tgz", - "integrity": "sha512-f+qapP2tx3X4GzcqAZm3RJ7ctAUIOqFLugmzSEeiYTxYdoohfLyxpvMyh2ErpNoIRDQCzraQ8zZ0G9UUr5KTxg==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/substrate/-/substrate-0.13.15.tgz", + "integrity": "sha512-DBXfXmw8YasjgkPN3O2dlagzQe6GCcL9TrydbTeKHBdENOjN7/pqpWkqDPk/kFL3++MM6DoQ2PRhXnjPI44hAA==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -635,9 +635,9 @@ } }, "node_modules/@airgap/tezos": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/tezos/-/tezos-0.13.15-beta.10.tgz", - "integrity": "sha512-mvcXr6SDaWOftWXv4IzFpKoDBJx++jH4suubxGqUrvgvJGDEVq5/Ynp6ce3m0nb9lL//T+IF73rmnqCCfkgmMA==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/tezos/-/tezos-0.13.15.tgz", + "integrity": "sha512-VSYvJZ2lk6BoRcY4UeOCrMHlvT5TirEE3hFyInPUtCtluoNcs5vmD1Txb5j2XivG9osuA8ZY08Hlsyj+e8meJQ==", "dependencies": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -26516,9 +26516,9 @@ }, "dependencies": { "@airgap/aeternity": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/aeternity/-/aeternity-0.13.15-beta.10.tgz", - "integrity": "sha512-Yi19sQMqQwZJ20fCbPUfpkLDBZLu7RangN8bePQotPaV45rZt45FplxNC+iCRdbAGbSUdWPhTeLzn+USXoA8TA==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/aeternity/-/aeternity-0.13.15.tgz", + "integrity": "sha512-Ooj8XFJZbK0v5tZHsX05yPMQGEVO2KfgycBx3H4asd6TqOiEaj9fE9ZVZia+v/uObHMgo3pWkuRZqfeuLBR4FQ==", "requires": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -26527,25 +26527,25 @@ } }, "@airgap/angular-core": { - "version": "0.0.37-beta.21", - "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.37-beta.21.tgz", - "integrity": "sha512-QVCsL6wGyqwuXwfSnpiI25PHDTbMRavdOPV2+i6KPJw/4/rV5q/hRs/mnyKQX8N2OFHGYOW4x/TBjS3ygc3hpA==", + "version": "0.0.37", + "resolved": "https://registry.npmjs.org/@airgap/angular-core/-/angular-core-0.0.37.tgz", + "integrity": "sha512-21TmmLmU+31/X/TyNj9pn71KQIJY1jzwDI5dWkYgSw7UjciYs+ch6muBGwK9fZyhoCBqnaQv98jBn+WSvGGV3w==", "requires": { "tslib": "^2.2.0" } }, "@airgap/angular-ngrx": { - "version": "0.0.37-beta.21", - "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.37-beta.21.tgz", - "integrity": "sha512-86E0IFCrCT/LAZccfj7K56tyEVnek5JUJsSTei/TL0CIJ5Zmy6pKPgdOEPUkQWka+rk1Zg/jYsWkeG2ESIwolQ==", + "version": "0.0.37", + "resolved": "https://registry.npmjs.org/@airgap/angular-ngrx/-/angular-ngrx-0.0.37.tgz", + "integrity": "sha512-eOWmX8O+WCyIvZrrAcDmasZivDIafhP9MITWxQVylHN8TblLCpJpXhD2LzN/qz+5389t4/O3lH/95htBwznM8w==", "requires": { "tslib": "^2.2.0" } }, "@airgap/astar": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/astar/-/astar-0.13.15-beta.10.tgz", - "integrity": "sha512-Sn/3Gaun9m5JqMpmiNx9fKXsdOTuzShkoYmtEV7Y00OdmExHQR3Dojfy2M/DJ1kjjVj4gT5COELFk/T/+tsp2g==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/astar/-/astar-0.13.15.tgz", + "integrity": "sha512-19KOTmpEdjrKoE6TNlv1Ba32bmFqTwjJCdHdx/cmtDETU5eKRMEwd5ZtQddgnbv5b3E0oYeePUoTdiMPg0Ucmg==", "requires": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -26698,9 +26698,9 @@ } }, "@airgap/bitcoin": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/bitcoin/-/bitcoin-0.13.15-beta.10.tgz", - "integrity": "sha512-G/vStubCH9DtSIqQ3Mh/loUBSMrfL+s+SJPPLIWUb4YKqXNS272jE1XqW6MTsfv9BTt40P9ZD1Nw8NLYwDvgQQ==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/bitcoin/-/bitcoin-0.13.15.tgz", + "integrity": "sha512-UXS25+x+XEw0HMTDEPJSCPlvdc9jSzv5vCnHdUUq8gcT/rvy5KmZPEqfGCL4XwZ5wrtclZhTS0BEvQ2s4EhJ7g==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -26710,9 +26710,9 @@ } }, "@airgap/coinlib-core": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/coinlib-core/-/coinlib-core-0.13.15-beta.10.tgz", - "integrity": "sha512-icwj44ScCimoBHZR8DBdOFg2bzlab8nk8K2DGlMfCPhMO8xq+huA9RFp9qqOGo4++sGc+kQDJGihyTugSmw0Lg==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/coinlib-core/-/coinlib-core-0.13.15.tgz", + "integrity": "sha512-JIxBZFanbjJ+WUYlhdgbnNRnHfE40FzVl7rkg6OYD8rJ0bH86GdmCYN7/U93r5mRy3HQ9CrRCREm/c4h0Ois3Q==", "requires": { "@stablelib/blake2b": "^1.0.1", "@stablelib/bytes": "^1.0.1", @@ -26724,9 +26724,9 @@ } }, "@airgap/coreum": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/coreum/-/coreum-0.13.15-beta.10.tgz", - "integrity": "sha512-BL8nCoEDU+ysJSF7rFX3CWNE0JQcBK3iIYsV7ZTayZ2/fMBP0E/rAoUoFye/nh7BRP0USj050jI9nyzJVqcG2Q==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/coreum/-/coreum-0.13.15.tgz", + "integrity": "sha512-KH4HPZ4I/CkiEj2uRvpVaGnk5TVLOq4k3IuNgkawq/py2RVmHlXzMUboY/PlT6/Uqtx3L+kYfJasA4V07byvNg==", "requires": { "@airgap/coinlib-core": "*", "@airgap/cosmos-core": "*", @@ -26736,9 +26736,9 @@ } }, "@airgap/cosmos": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/cosmos/-/cosmos-0.13.15-beta.10.tgz", - "integrity": "sha512-TA4OaMh08jgDuUgOggB2cUqvUOCRK5uoNYf2VCsFtgCucGUkIQ3BeDi7n7PhxpF9cdcMb/S/PDkEh/mz3dtX5g==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/cosmos/-/cosmos-0.13.15.tgz", + "integrity": "sha512-fyUeMwJvNzlCQgdNT6kA9YG2S8daFN5nvG5RI2EojCs5esWBetD13wvyX4zXSf1riMpq1KpgKQLzqfXsifYxlw==", "requires": { "@airgap/coinlib-core": "*", "@airgap/cosmos-core": "*", @@ -26748,9 +26748,9 @@ } }, "@airgap/cosmos-core": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/cosmos-core/-/cosmos-core-0.13.15-beta.10.tgz", - "integrity": "sha512-jID1O5Tpuydrt6wibsM1ergRHDUQ1GdSEcHHc9W7B6EZZL+9HS0j1Ehx+8naMwqrNkvqaM4wOCVI9hr2bX9b8g==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/cosmos-core/-/cosmos-core-0.13.15.tgz", + "integrity": "sha512-ptyfJS/rVcP/auipoMfhbCGTpciTlUUKnN+MwIuwNC5SUSCwXkOQYV+t+5fcPbQ3X7tCfjj5QRWi2ZSKWrL0DA==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -26759,9 +26759,9 @@ } }, "@airgap/crypto": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/crypto/-/crypto-0.13.15-beta.10.tgz", - "integrity": "sha512-PU8+3UGxYfpToAgodUAiex7zfLAdcAz+WMgxFYGcJQ/E9pOJq7t8Nc12b3dOAlIpoGtj3iqlN0AR7rf/BfG50A==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/crypto/-/crypto-0.13.15.tgz", + "integrity": "sha512-CLizaNFFfu7RhmT7wyhhw2D07DuUH6zzmzn5cSYAJlmmhlOTFWbwxHGDUWOonEzINmzrmZFgnZ4tmpANVzeMgg==", "requires": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -26778,9 +26778,9 @@ } }, "@airgap/ethereum": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/ethereum/-/ethereum-0.13.15-beta.10.tgz", - "integrity": "sha512-zDZVrI53bzXCP5LOk7dojrxXkqcNFxHd0gCGiwiMKJb2h45qf27FLZMuCI8WzyfPtAo1tZhxzVqCAWt8hRYUCg==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/ethereum/-/ethereum-0.13.15.tgz", + "integrity": "sha512-vsF5S1HbOZWYR70/I79T7y32A7NJzvh8oLNZYUmdYwvIiZs3YzsyUO45UTpIytv3EAf6peDA9wUSUhOm6zwyiA==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -26792,9 +26792,9 @@ } }, "@airgap/groestlcoin": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/groestlcoin/-/groestlcoin-0.13.15-beta.10.tgz", - "integrity": "sha512-uTzPud+ti2SCHmGzxU57dmpC5Msn+pDffDf++Xt05XSUMmCqDVAW/7RuJHoFxPxdYq7WFBmw+Slard5/1qPIiw==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/groestlcoin/-/groestlcoin-0.13.15.tgz", + "integrity": "sha512-btt20YQh1rVHcfixTlHqfMK0v33j82y/l296FASMukQLY2rlK00u4IaGvo6b3QmcjZsgLZ+W8c2lNOtIMWlG1Q==", "requires": { "@airgap/bitcoin": "*", "@airgap/coinlib-core": "*", @@ -26803,9 +26803,9 @@ } }, "@airgap/icp": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/icp/-/icp-0.13.15-beta.10.tgz", - "integrity": "sha512-rB9u5YuTKrUzVrmE9wcgbDkyFJwric2hlEiENy42fYbj64IB++GCkjyUiC5kXLKl5sjQkOBIW7z7mT7B02avBg==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/icp/-/icp-0.13.15.tgz", + "integrity": "sha512-Ku/6Oxlg9DXjKZhbov4ypwQkNpA8SIIk0CVcvA7yPxbumApa+l4svEXMX14nLJ6xF86oKrtW6EMOqOg3wH9Z+g==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -26864,18 +26864,18 @@ } }, "@airgap/module-kit": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/module-kit/-/module-kit-0.13.15-beta.10.tgz", - "integrity": "sha512-nYJkKvf8+tS6Q2Lt7THnEDtBtg1omKwuzEcHtavShWyugTqhmmMcGBKVwrMOI0gNdxfC4ap+BxFDCdrOZXq/ZA==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/module-kit/-/module-kit-0.13.15.tgz", + "integrity": "sha512-n2hxPTWpvtJcTL8MRWQNkj0Su9ovg5d43i8H+YaWzcNnFt1Fl2FidmIS3F+JGntqfMQgzTCQnNylI+kWV4zjsg==", "requires": { "@airgap/coinlib-core": "*", "@airgap/serializer": "*" } }, "@airgap/moonbeam": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/moonbeam/-/moonbeam-0.13.15-beta.10.tgz", - "integrity": "sha512-CahZ8Gv+m684KBcjJrHyXdCWsVbFvZUXRcNnIYyR3Iey2OpxTiWZWPKl8FVsq4zl/UeXPB3iZGfOkf/5E5/D0g==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/moonbeam/-/moonbeam-0.13.15.tgz", + "integrity": "sha512-29BbL6tsi7Fl6M9ks1eqjlbTNrCf92v14nlWkYxJ0O/EDMkAOe7OLRLDlch0+5viltsHRKtUe1xJ6HgFojfVXQ==", "requires": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -26884,9 +26884,9 @@ } }, "@airgap/polkadot": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/polkadot/-/polkadot-0.13.15-beta.10.tgz", - "integrity": "sha512-lqDlSx1GfyA9Xsi1UrDfcJkFuWuDeiNqTS6HLokCfR+PO/g3HawKEg3bINtLnv2uAKvclKx8iylbDq+oxZamxA==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/polkadot/-/polkadot-0.13.15.tgz", + "integrity": "sha512-QbY0R0r0eABbfFn75shR3cHYP/15yPjNOSweBp0r9gCuVa9azClg0j3CPxH8jMCZqTDIuzrZRKrGpWPwMAAoTg==", "requires": { "@airgap/coinlib-core": "*", "@airgap/module-kit": "*", @@ -26899,17 +26899,17 @@ "integrity": "sha512-IMODbGPTBYKuO5ztiHX9C1PTlhqZvmVWv7m7zj5+VMcbBxrk4+jBAf7FYTH5l+IUsNMaHBOuh8Qq3A1b/pm7jQ==" }, "@airgap/serializer": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/serializer/-/serializer-0.13.15-beta.10.tgz", - "integrity": "sha512-woa1UG/UJQxlLuAxWpxxbHdIyPDGzNiEbdmBMe7HGi0IMnT+4SRqhQcLGBUSoPG4zB2hy00U4eICNGGaJDqhLg==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/serializer/-/serializer-0.13.15.tgz", + "integrity": "sha512-5vOthazh7KFYpRO2i9lZI/D5LOCGxOvaTYIIv+b4DZxgKcOzOinnL/+t2HS8L1H1MF3fIdy90yJBYwnVyMKq2w==", "requires": { "@airgap/coinlib-core": "*" } }, "@airgap/substrate": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/substrate/-/substrate-0.13.15-beta.10.tgz", - "integrity": "sha512-f+qapP2tx3X4GzcqAZm3RJ7ctAUIOqFLugmzSEeiYTxYdoohfLyxpvMyh2ErpNoIRDQCzraQ8zZ0G9UUr5KTxg==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/substrate/-/substrate-0.13.15.tgz", + "integrity": "sha512-DBXfXmw8YasjgkPN3O2dlagzQe6GCcL9TrydbTeKHBdENOjN7/pqpWkqDPk/kFL3++MM6DoQ2PRhXnjPI44hAA==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", @@ -26920,9 +26920,9 @@ } }, "@airgap/tezos": { - "version": "0.13.15-beta.10", - "resolved": "https://registry.npmjs.org/@airgap/tezos/-/tezos-0.13.15-beta.10.tgz", - "integrity": "sha512-mvcXr6SDaWOftWXv4IzFpKoDBJx++jH4suubxGqUrvgvJGDEVq5/Ynp6ce3m0nb9lL//T+IF73rmnqCCfkgmMA==", + "version": "0.13.15", + "resolved": "https://registry.npmjs.org/@airgap/tezos/-/tezos-0.13.15.tgz", + "integrity": "sha512-VSYvJZ2lk6BoRcY4UeOCrMHlvT5TirEE3hFyInPUtCtluoNcs5vmD1Txb5j2XivG9osuA8ZY08Hlsyj+e8meJQ==", "requires": { "@airgap/coinlib-core": "*", "@airgap/crypto": "*", diff --git a/package.json b/package.json index 6acb8f54b..0f69c4424 100644 --- a/package.json +++ b/package.json @@ -55,27 +55,27 @@ } }, "dependencies": { - "@airgap/aeternity": "0.13.15-beta.10", - "@airgap/angular-core": "0.0.37-beta.21", - "@airgap/angular-ngrx": "0.0.37-beta.21", - "@airgap/astar": "0.13.15-beta.10", + "@airgap/aeternity": "0.13.15", + "@airgap/angular-core": "0.0.37", + "@airgap/angular-ngrx": "0.0.37", + "@airgap/astar": "0.13.15", "@airgap/beacon-sdk": "3.1.5-beta.0", - "@airgap/bitcoin": "0.13.15-beta.10", - "@airgap/coinlib-core": "0.13.15-beta.10", - "@airgap/coreum": "0.13.15-beta.10", - "@airgap/cosmos": "0.13.15-beta.10", - "@airgap/cosmos-core": "0.13.15-beta.10", - "@airgap/crypto": "0.13.15-beta.10", - "@airgap/ethereum": "0.13.15-beta.10", - "@airgap/groestlcoin": "0.13.15-beta.10", - "@airgap/icp": "0.13.15-beta.10", - "@airgap/module-kit": "0.13.15-beta.10", - "@airgap/moonbeam": "0.13.15-beta.10", - "@airgap/polkadot": "0.13.15-beta.10", + "@airgap/bitcoin": "0.13.15", + "@airgap/coinlib-core": "0.13.15", + "@airgap/coreum": "0.13.15", + "@airgap/cosmos": "0.13.15", + "@airgap/cosmos-core": "0.13.15", + "@airgap/crypto": "0.13.15", + "@airgap/ethereum": "0.13.15", + "@airgap/groestlcoin": "0.13.15", + "@airgap/icp": "0.13.15", + "@airgap/module-kit": "0.13.15", + "@airgap/moonbeam": "0.13.15", + "@airgap/polkadot": "0.13.15", "@airgap/sapling-wasm": "0.0.7", - "@airgap/serializer": "0.13.15-beta.10", - "@airgap/substrate": "0.13.15-beta.10", - "@airgap/tezos": "0.13.15-beta.10", + "@airgap/serializer": "0.13.15", + "@airgap/substrate": "0.13.15", + "@airgap/tezos": "0.13.15", "@angular/animations": "^11.2.9", "@angular/common": "^11.2.9", "@angular/core": "^11.2.9",