@1001-digital/components.evm 1.3.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1001-digital/components.evm",
3
- "version": "1.3.0",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "sideEffects": [
6
6
  "*.css"
@@ -18,10 +18,10 @@
18
18
  "@wagmi/vue": ">=0.5.0",
19
19
  "viem": ">=2.0.0",
20
20
  "vue": "^3.5.0",
21
- "@1001-digital/components": "^1.5.0"
21
+ "@1001-digital/components": "^2.0.0"
22
22
  },
23
23
  "dependencies": {
24
- "@1001-digital/dweb-fetch": "^0.1.5",
24
+ "@1001-digital/dweb-fetch": "^0.1.6",
25
25
  "@1001-digital/wagmi-in-app-wallet": "^0.1.0",
26
26
  "@types/qrcode": "^1.5.6",
27
27
  "qrcode": "^1.5.4"
@@ -11,4 +11,5 @@ export const clientOnlyComponents = [
11
11
  'EvmWalletConnectQR',
12
12
  'EvmSiwe',
13
13
  'EvmSiweDialog',
14
+ 'EvmSidebarProfile',
14
15
  ]
@@ -12,7 +12,7 @@
12
12
  class="link muted small"
13
13
  @click="resetConnection"
14
14
  >
15
- <Icon type="chevron-left" />
15
+ <Icon name="chevron-left" />
16
16
  <span>Back</span>
17
17
  </Button>
18
18
  </template>
@@ -52,7 +52,7 @@
52
52
  v-else
53
53
  class="default-wallet-icon"
54
54
  >
55
- <Icon type="wallet" />
55
+ <Icon name="wallet" />
56
56
  </div>
57
57
  <span>{{ connector.name }}</span>
58
58
  </Button>
@@ -83,7 +83,7 @@
83
83
  target="_blank"
84
84
  class="link muted small"
85
85
  >
86
- <Icon type="help" />
86
+ <Icon name="help" />
87
87
  <span>New to wallets?</span>
88
88
  </Button>
89
89
  </div>
@@ -9,7 +9,7 @@
9
9
  @click="copyUri"
10
10
  class="copy-uri tertiary small"
11
11
  >
12
- <Icon :type="isCopied ? 'check' : 'copy'" />
12
+ <Icon :name="isCopied ? 'check' : 'copy'" />
13
13
  <span>
14
14
  {{ isCopied ? 'Copied' : 'Copy Link' }}
15
15
  </span>
@@ -12,14 +12,14 @@
12
12
  class="block"
13
13
  @click="startGenerate"
14
14
  >
15
- <Icon type="plus" />
15
+ <Icon name="plus" />
16
16
  <span>Create New Wallet</span>
17
17
  </Button>
18
18
  <Button
19
19
  class="block"
20
20
  @click="step = 'restore'"
21
21
  >
22
- <Icon type="key" />
22
+ <Icon name="key" />
23
23
  <span>Use Existing Recovery Key</span>
24
24
  </Button>
25
25
  </div>
@@ -27,7 +27,7 @@
27
27
  class="link muted small"
28
28
  @click="$emit('back')"
29
29
  >
30
- <Icon type="chevron-left" />
30
+ <Icon name="chevron-left" />
31
31
  <span>Back</span>
32
32
  </Button>
33
33
  </div>
@@ -71,7 +71,7 @@
71
71
  class="link muted small"
72
72
  @click="step = 'choose'"
73
73
  >
74
- <Icon type="chevron-left" />
74
+ <Icon name="chevron-left" />
75
75
  <span>Back</span>
76
76
  </Button>
77
77
  </div>
@@ -102,7 +102,7 @@
102
102
  class="link muted small"
103
103
  @click="step = 'choose'"
104
104
  >
105
- <Icon type="chevron-left" />
105
+ <Icon name="chevron-left" />
106
106
  <span>Back</span>
107
107
  </Button>
108
108
  </div>
@@ -8,7 +8,7 @@
8
8
  class="link muted small"
9
9
  @click="$emit('back')"
10
10
  >
11
- <Icon type="chevron-left" />
11
+ <Icon name="chevron-left" />
12
12
  <span>Back</span>
13
13
  </Button>
14
14
  </template>
@@ -41,7 +41,7 @@
41
41
  @click="copyAddress"
42
42
  >
43
43
  <span>{{ shortAddr }}</span>
44
- <Icon :type="copied ? 'check' : 'copy'" />
44
+ <Icon :name="copied ? 'check' : 'copy'" />
45
45
  </Button>
46
46
  </div>
47
47
 
@@ -50,7 +50,7 @@
50
50
 
51
51
  <EvmSwitchNetwork class-name="block">
52
52
  <template #default="{ currentChain }">
53
- <Icon type="wallet" />
53
+ <Icon name="wallet" />
54
54
  <span>Switch Network ({{ currentChain?.name || 'Unknown' }})</span>
55
55
  </template>
56
56
  </EvmSwitchNetwork>
@@ -61,7 +61,7 @@
61
61
  :to="`https://app.ens.domains/${ensName}`"
62
62
  target="_blank"
63
63
  >
64
- <Icon type="link" />
64
+ <Icon name="link" />
65
65
  <span>Manage ENS</span>
66
66
  </Button>
67
67
 
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <div class="evm-sidebar-profile">
3
+ <EvmConnectDialog
4
+ v-if="!isConnected"
5
+ className="block"
6
+ />
7
+ <EvmProfile
8
+ v-else
9
+ class-name="sidebar-profile-trigger"
10
+ @disconnected="$emit('disconnected')"
11
+ >
12
+ <template #default="{ address, display, ensName }">
13
+ <slot
14
+ :address="address"
15
+ :display="display"
16
+ :ens-name="ensName"
17
+ >
18
+ <EvmAvatar :address="address" />
19
+ <span class="sidebar-profile-name">{{ display }}</span>
20
+ </slot>
21
+ </template>
22
+ <template
23
+ v-if="$slots.actions"
24
+ #actions
25
+ >
26
+ <slot name="actions" />
27
+ </template>
28
+ </EvmProfile>
29
+ </div>
30
+ </template>
31
+
32
+ <script setup lang="ts">
33
+ import { useConnection } from '@wagmi/vue'
34
+ import EvmAvatar from './EvmAvatar.vue'
35
+ import EvmProfile from './EvmProfile.vue'
36
+ import type { EvmSidebarProfileEmits } from '../types'
37
+
38
+ defineEmits<EvmSidebarProfileEmits>()
39
+
40
+ const { isConnected } = useConnection()
41
+ </script>
42
+
43
+ <style scoped>
44
+ .evm-sidebar-profile {
45
+ margin-block-start: auto;
46
+ border-block-start: var(--border);
47
+ padding: var(--spacer-sm);
48
+ }
49
+
50
+ :deep(.sidebar-profile-trigger) {
51
+ display: flex;
52
+ align-items: center;
53
+ gap: var(--spacer-sm);
54
+ inline-size: 100%;
55
+ padding: var(--spacer-sm);
56
+ border-radius: var(--radius);
57
+ }
58
+
59
+ .sidebar-profile-name {
60
+ font-size: var(--font-sm);
61
+ font-weight: 500;
62
+ overflow: hidden;
63
+ text-overflow: ellipsis;
64
+ white-space: nowrap;
65
+ }
66
+ </style>
@@ -10,7 +10,7 @@
10
10
 
11
11
  <FormItem>
12
12
  <template #prefix>
13
- <Icon type="lucide:search" />
13
+ <Icon name="lucide:search" />
14
14
  </template>
15
15
  <input
16
16
  v-model="searchQuery"
@@ -61,7 +61,7 @@
61
61
  class="link muted small"
62
62
  @click="$emit('back')"
63
63
  >
64
- <Icon type="chevron-left" />
64
+ <Icon name="chevron-left" />
65
65
  <span>Back</span>
66
66
  </Button>
67
67
  </div>
@@ -1,10 +1,10 @@
1
- import { ref, computed, watch, type Ref, type WatchStopHandle } from 'vue'
1
+ import { ref, computed, watch, onScopeDispose, type Ref } from 'vue'
2
2
  import { formatEther, formatGwei } from 'viem'
3
3
  import { getGasPrice } from '@wagmi/core'
4
4
  import { useConfig, useBlockNumber } from '@wagmi/vue'
5
5
 
6
- let priceWatcher: WatchStopHandle | null = null
7
6
  const price: Ref<bigint> = ref(0n)
7
+ let watcherCount = 0
8
8
 
9
9
  export const useGasPrice = () => {
10
10
  const config = useConfig()
@@ -14,10 +14,15 @@ export const useGasPrice = () => {
14
14
  price.value = await getGasPrice(config)
15
15
  }
16
16
 
17
- if (!priceWatcher) {
18
- updatePrice()
19
- priceWatcher = watch(blockNumber, () => updatePrice())
20
- }
17
+ if (watcherCount === 0) updatePrice()
18
+ watcherCount++
19
+
20
+ const stopWatcher = watch(blockNumber, () => updatePrice())
21
+
22
+ onScopeDispose(() => {
23
+ stopWatcher()
24
+ watcherCount--
25
+ })
21
26
 
22
27
  const unitPrice = computed(() => ({
23
28
  wei: price.value,
@@ -74,11 +74,12 @@ export const usePriceFeed = () => {
74
74
  const ethUSD = computed(() =>
75
75
  state.ethUSDRaw ? state.ethUSDRaw / BigInt(1e8) : 0n,
76
76
  )
77
- const ethUSC = computed(() =>
77
+ // Chainlink returns 8 decimals; dividing by 1e6 keeps 2 decimal digits (cents)
78
+ const ethUSDCents = computed(() =>
78
79
  state.ethUSDRaw ? state.ethUSDRaw / BigInt(1e6) : 0n,
79
80
  )
80
81
  const ethUSDFormatted = computed(() =>
81
- formatPrice(Number(ethUSC.value) / 100, 2),
82
+ formatPrice(Number(ethUSDCents.value) / 100, 2),
82
83
  )
83
84
 
84
85
  const weiToUSD = (wei: bigint) => {
@@ -108,7 +109,7 @@ export const usePriceFeed = () => {
108
109
  return {
109
110
  ethUSDRaw: computed(() => state.ethUSDRaw),
110
111
  ethUSD,
111
- ethUSC,
112
+ ethUSDCents,
112
113
  ethUSDFormatted,
113
114
  weiToUSD,
114
115
  fetchPrice,
@@ -47,6 +47,10 @@ export const useSiwe = () => {
47
47
 
48
48
  const nonce = await options.getNonce()
49
49
 
50
+ if (typeof window === 'undefined') {
51
+ throw new Error('SIWE sign-in requires a browser environment')
52
+ }
53
+
50
54
  const messageParams: SiweMessageParams = {
51
55
  domain: options.domain || window.location.host,
52
56
  address: currentAddress,
package/src/index.ts CHANGED
@@ -11,6 +11,7 @@ export type {
11
11
  EvmConnectDialogEmits,
12
12
  EvmProfileProps,
13
13
  EvmProfileEmits,
14
+ EvmSidebarProfileEmits,
14
15
  EvmSwitchNetworkProps,
15
16
  EvmSwitchNetworkEmits,
16
17
  EvmConnectorQRProps,
@@ -80,6 +81,7 @@ export { default as EvmConnect } from './components/EvmConnect.vue'
80
81
  export { default as EvmConnectDialog } from './components/EvmConnectDialog.vue'
81
82
  export { default as EvmConnectionStatus } from './components/EvmConnectionStatus.vue'
82
83
  export { default as EvmProfile } from './components/EvmProfile.vue'
84
+ export { default as EvmSidebarProfile } from './components/EvmSidebarProfile.vue'
83
85
  export { default as EvmSwitchNetwork } from './components/EvmSwitchNetwork.vue'
84
86
  export { default as EvmConnectorQR } from './components/EvmConnectorQR.vue'
85
87
  export { default as EvmMetaMaskQR } from './components/EvmMetaMaskQR.vue'
package/src/types.ts CHANGED
@@ -136,6 +136,11 @@ export interface EvmSiweEmits {
136
136
  error: [error: string]
137
137
  }
138
138
 
139
+ // EvmSidebarProfile
140
+ export interface EvmSidebarProfileEmits {
141
+ disconnected: []
142
+ }
143
+
139
144
  // EvmSiweDialog
140
145
  export interface EvmSiweDialogProps extends EvmSiweProps {
141
146
  className?: string
@@ -29,6 +29,9 @@ export function createCache<T>(ttl: number, max: number) {
29
29
  entries.delete(key)
30
30
  return undefined
31
31
  }
32
+ // Move to end for LRU ordering
33
+ entries.delete(key)
34
+ entries.set(key, entry)
32
35
  return entry.data
33
36
  }
34
37