diff --git a/package-lock.json b/package-lock.json
index 2e6fc37..a3fb6e1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "wallet",
- "version": "1.23.1",
+ "version": "1.23.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "wallet",
- "version": "1.23.1",
+ "version": "1.23.2",
"license": "GPL",
"dependencies": {
"@chenfengyuan/vue-qrcode": "^2.0.0",
diff --git a/package.json b/package.json
index 8ea3ee2..0ff6d2c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "wallet",
- "version": "1.23.1",
+ "version": "1.23.2",
"description": "Web wallet for managing $EDGE",
"private": true,
"license": "GPL",
diff --git a/src/components/tx/SendModal.vue b/src/components/tx/SendModal.vue
index fd0d803..8521bae 100644
--- a/src/components/tx/SendModal.vue
+++ b/src/components/tx/SendModal.vue
@@ -11,13 +11,32 @@
@@ -187,7 +206,7 @@ import Modal from '../Modal.vue'
import Radio from '../Radio.vue'
import { helpers } from '@vuelidate/validators'
import { mapState } from 'vuex'
-import { parseAmount } from '../../utils/form'
+import { parseAmount, truncateAddress } from '../../utils/form'
import useVuelidate from '@vuelidate/core'
const memoRegexp = /^[a-zA-Z0-9\s-]{0,32}$/
@@ -216,7 +235,9 @@ export default {
passwordError: '',
completedTx: null,
- submitError: ''
+ submitError: '',
+
+ showRecipientDropdown: false
}
},
validations() {
@@ -239,7 +260,18 @@ export default {
}
},
computed: {
- ...mapState(['address', 'balance', 'nextNonce']),
+ ...mapState(['address', 'balance', 'nextNonce', 'wallets', 'activeWalletId']),
+ otherWallets() {
+ return this.wallets.filter(w => w.id !== this.activeWalletId)
+ },
+ filteredWallets() {
+ const query = this.recipient.trim().toLowerCase()
+ if (!query) return this.otherWallets
+ return this.otherWallets.filter(w =>
+ w.name.toLowerCase().includes(query) ||
+ w.address.toLowerCase().includes(query)
+ )
+ },
amountParsed() {
return parseAmount(this.amount)
},
@@ -266,6 +298,21 @@ export default {
this.reset()
this.close()
},
+ onRecipientFocus() {
+ this.showRecipientDropdown = true
+ },
+ onRecipientEsc() {
+ this.showRecipientDropdown = false
+ },
+ onRecipientBlur() {
+ // Small delay so mousedown on dropdown item fires before hide
+ setTimeout(() => { this.showRecipientDropdown = false }, 150)
+ },
+ selectRecipient(wallet) {
+ this.recipient = wallet.address
+ this.showRecipientDropdown = false
+ },
+ truncateAddress,
async checkPassword() {
this.v$.password.$reset()
if (await storage.comparePassword(this.password)) {
@@ -298,6 +345,7 @@ export default {
this.completedTx = null
this.submitError = ''
+ this.showRecipientDropdown = false
this.v$.$reset()
},
@@ -370,4 +418,44 @@ export default {
color: #0ecc5f;
padding-left: 10px;
}
+
+.recipient-input-wrap {
+ position: relative;
+}
+
+.recipient-suggestions {
+ @apply absolute left-0 right-0 rounded-lg z-20 py-6;
+ top: 100%;
+ margin-top: 6px;
+ max-height: 160px;
+ overflow-y: auto;
+ background: #1d1d1d;
+ border: 1px solid rgba(255, 255, 255, 0.15);
+ box-shadow: 0 8px 30px rgba(0, 0, 0, 0.8);
+}
+
+.recipient-suggestions__header {
+ @apply px-12 text-gray-400;
+ padding-top: 4px;
+ padding-bottom: 8px;
+ font-size: 11px;
+ text-transform: uppercase;
+ letter-spacing: 0.05em;
+}
+
+.recipient-suggestions__item {
+ @apply flex items-center justify-between w-full px-12 py-10 text-gray transition-colors cursor-pointer;
+ @apply hover:text-white hover:bg-gray-700 hover:bg-opacity-25;
+ background: none;
+ border: none;
+ font-size: 13px;
+}
+
+.recipient-suggestions__name {
+ @apply font-medium text-white text-sm leading-tight;
+}
+
+.recipient-suggestions__address {
+ @apply text-sm2 text-gray-400 leading-tight;
+}
diff --git a/src/components/wallet/WalletIndicator.vue b/src/components/wallet/WalletIndicator.vue
index 4b90dde..e8729a9 100644
--- a/src/components/wallet/WalletIndicator.vue
+++ b/src/components/wallet/WalletIndicator.vue
@@ -60,6 +60,7 @@