@1001-digital/components 1.2.1 → 1.2.3

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.
Files changed (45) hide show
  1. package/package.json +1 -21
  2. package/src/index.ts +0 -3
  3. package/src/evm/assets/wallets/coinbase.svg +0 -4
  4. package/src/evm/assets/wallets/in-app.svg +0 -5
  5. package/src/evm/assets/wallets/metamask.svg +0 -1
  6. package/src/evm/assets/wallets/phantom.svg +0 -4
  7. package/src/evm/assets/wallets/rabby.svg +0 -24
  8. package/src/evm/assets/wallets/rainbow.svg +0 -59
  9. package/src/evm/assets/wallets/safe.png +0 -0
  10. package/src/evm/assets/wallets/walletconnect.svg +0 -1
  11. package/src/evm/components/EvmAccount.vue +0 -28
  12. package/src/evm/components/EvmAvatar.vue +0 -62
  13. package/src/evm/components/EvmConnect.vue +0 -301
  14. package/src/evm/components/EvmConnectDialog.vue +0 -75
  15. package/src/evm/components/EvmConnectionStatus.vue +0 -13
  16. package/src/evm/components/EvmConnectorQR.vue +0 -86
  17. package/src/evm/components/EvmInAppWalletSetup.vue +0 -251
  18. package/src/evm/components/EvmMetaMaskQR.vue +0 -34
  19. package/src/evm/components/EvmProfile.vue +0 -186
  20. package/src/evm/components/EvmSeedPhraseInput.vue +0 -193
  21. package/src/evm/components/EvmSiwe.vue +0 -190
  22. package/src/evm/components/EvmSiweDialog.vue +0 -93
  23. package/src/evm/components/EvmSwitchNetwork.vue +0 -132
  24. package/src/evm/components/EvmTransactionFlow.vue +0 -353
  25. package/src/evm/components/EvmWalletConnectQR.vue +0 -13
  26. package/src/evm/components/EvmWalletConnectWallets.vue +0 -200
  27. package/src/evm/composables/base.ts +0 -7
  28. package/src/evm/composables/chainId.ts +0 -42
  29. package/src/evm/composables/ens.ts +0 -113
  30. package/src/evm/composables/gasPrice.ts +0 -37
  31. package/src/evm/composables/priceFeed.ts +0 -116
  32. package/src/evm/composables/siwe.ts +0 -89
  33. package/src/evm/composables/uri.ts +0 -12
  34. package/src/evm/composables/walletExplorer.ts +0 -130
  35. package/src/evm/config.ts +0 -35
  36. package/src/evm/connectors/inAppWallet.ts +0 -5
  37. package/src/evm/index.ts +0 -60
  38. package/src/evm/utils/addresses.ts +0 -6
  39. package/src/evm/utils/cache.ts +0 -59
  40. package/src/evm/utils/chains.ts +0 -32
  41. package/src/evm/utils/ens.ts +0 -116
  42. package/src/evm/utils/format-eth.ts +0 -15
  43. package/src/evm/utils/price.ts +0 -17
  44. package/src/evm/utils/siwe.ts +0 -70
  45. package/src/evm/utils/uri.ts +0 -24
@@ -1,193 +0,0 @@
1
- <template>
2
- <div class="seed-phrase-input">
3
- <div class="seed-phrase-grid">
4
- <div
5
- v-for="(_, i) in 12"
6
- :key="i"
7
- class="seed-word"
8
- :class="{ invalid: words[i] && !isValidWord(words[i]) }"
9
- >
10
- <label :for="`seed-word-${i}`">{{ i + 1 }}</label>
11
- <input
12
- :id="`seed-word-${i}`"
13
- :ref="
14
- (el) => {
15
- if (el) inputRefs[i] = el as HTMLInputElement
16
- }
17
- "
18
- v-model="words[i]"
19
- type="text"
20
- autocomplete="off"
21
- autocapitalize="none"
22
- spellcheck="false"
23
- :disabled="disabled"
24
- @keydown="onKeydown($event, i)"
25
- @paste="onPaste($event, i)"
26
- @input="onInput(i)"
27
- />
28
- </div>
29
- </div>
30
- </div>
31
- </template>
32
-
33
- <script setup lang="ts">
34
- import { ref, watch, computed, onMounted } from 'vue'
35
- import { english } from 'viem/accounts'
36
-
37
- const props = defineProps<{
38
- modelValue?: string
39
- disabled?: boolean
40
- }>()
41
-
42
- const emit = defineEmits<{
43
- 'update:modelValue': [value: string]
44
- valid: [isValid: boolean]
45
- submit: []
46
- }>()
47
-
48
- const wordSet = new Set(english)
49
-
50
- const words = ref<string[]>(Array.from({ length: 12 }, () => ''))
51
- const inputRefs = ref<HTMLInputElement[]>([])
52
-
53
- function isValidWord(word: string): boolean {
54
- return wordSet.has(word.trim().toLowerCase())
55
- }
56
-
57
- const isValid = computed(() =>
58
- words.value.every((w) => w.trim() !== '' && isValidWord(w)),
59
- )
60
-
61
- const phrase = computed(() =>
62
- words.value.map((w) => w.trim().toLowerCase()).join(' '),
63
- )
64
-
65
- watch(
66
- () => props.modelValue,
67
- (val) => {
68
- if (!val) return
69
- const incoming = val.trim().split(/\s+/)
70
- if (incoming.length === 12) {
71
- for (let i = 0; i < 12; i++) {
72
- words.value[i] = incoming[i]!
73
- }
74
- }
75
- },
76
- { immediate: true },
77
- )
78
-
79
- watch(phrase, (val) => {
80
- emit('update:modelValue', val)
81
- })
82
-
83
- watch(isValid, (val) => {
84
- emit('valid', val)
85
- })
86
-
87
- function focusInput(index: number) {
88
- const el = inputRefs.value[index]
89
- if (el) {
90
- el.focus()
91
- el.select()
92
- }
93
- }
94
-
95
- function onKeydown(event: KeyboardEvent, index: number) {
96
- if (event.key === ' ' || (event.key === 'Enter' && index < 11)) {
97
- event.preventDefault()
98
- focusInput(index + 1)
99
- } else if (event.key === 'Enter' && index === 11 && isValid.value) {
100
- event.preventDefault()
101
- emit('submit')
102
- } else if (
103
- event.key === 'Backspace' &&
104
- words.value[index] === '' &&
105
- index > 0
106
- ) {
107
- event.preventDefault()
108
- focusInput(index - 1)
109
- } else if (event.key === 'Tab' && !event.shiftKey && index === 11) {
110
- // Allow natural tab out
111
- } else if (event.key === 'Tab' && event.shiftKey && index === 0) {
112
- // Allow natural tab out
113
- }
114
- }
115
-
116
- function onPaste(event: ClipboardEvent, index: number) {
117
- const text = event.clipboardData?.getData('text')
118
- if (!text) return
119
-
120
- const pasted = text.trim().split(/\s+/)
121
- if (pasted.length > 1) {
122
- event.preventDefault()
123
- for (let i = 0; i < pasted.length && index + i < 12; i++) {
124
- words.value[index + i] = pasted[i]!.toLowerCase()
125
- }
126
- const nextIndex = Math.min(index + pasted.length, 11)
127
- focusInput(nextIndex)
128
- }
129
- }
130
-
131
- function onInput(index: number) {
132
- // Auto-advance if the word contains a space (mobile autocomplete)
133
- const val = words.value[index]
134
- if (val?.includes(' ')) {
135
- const parts = val.trim().split(/\s+/)
136
- words.value[index] = parts[0]!
137
- if (parts.length > 1 && index < 11) {
138
- for (let i = 1; i < parts.length && index + i < 12; i++) {
139
- words.value[index + i] = parts[i]!
140
- }
141
- focusInput(Math.min(index + parts.length, 11))
142
- }
143
- }
144
- }
145
-
146
- onMounted(() => {
147
- if (!props.disabled) {
148
- focusInput(0)
149
- }
150
- })
151
- </script>
152
-
153
- <style scoped>
154
- .seed-phrase-grid {
155
- display: grid;
156
- grid-template-columns: repeat(3, 1fr);
157
- gap: var(--spacer-sm);
158
- }
159
-
160
-
161
- .seed-word {
162
- display: flex;
163
- align-items: center;
164
- gap: var(--spacer-sm);
165
- border: var(--border);
166
- border-radius: var(--border-radius);
167
- padding: var(--spacer-sm);
168
- transition: border-color var(--speed);
169
-
170
- &:focus-within {
171
- border-color: var(--accent);
172
- }
173
-
174
- &.invalid {
175
- border-color: var(--error);
176
- }
177
-
178
- label {
179
- font-size: var(--font-xs);
180
- color: var(--muted);
181
- min-width: 1.5em;
182
- text-align: right;
183
- user-select: none;
184
- }
185
-
186
- input {
187
- all: unset;
188
- width: 100%;
189
- font-size: var(--font-sm);
190
- font-family: var(--font-mono, monospace);
191
- }
192
- }
193
- </style>
@@ -1,190 +0,0 @@
1
- <template>
2
- <Loading
3
- v-if="step === 'signing'"
4
- spinner
5
- stacked
6
- :txt="connector?.name
7
- ? `Requesting signature from ${connector.name}...`
8
- : 'Requesting signature...'"
9
- />
10
-
11
- <Loading
12
- v-else-if="step === 'verifying'"
13
- spinner
14
- stacked
15
- txt="Verifying signature..."
16
- />
17
-
18
- <template v-else-if="step === 'complete'">
19
- <slot name="complete">
20
- <Alert type="info">
21
- <p>Successfully signed in.</p>
22
- </Alert>
23
- </slot>
24
- </template>
25
-
26
- <template v-else-if="step === 'error'">
27
- <Alert type="error">
28
- <p>{{ errorMessage }}</p>
29
- </Alert>
30
- <Button
31
- class="secondary"
32
- @click="signIn"
33
- >Try Again</Button>
34
- </template>
35
-
36
- <template v-else>
37
- <slot name="idle">
38
- <p v-if="props.statement">{{ props.statement }}</p>
39
- </slot>
40
- <Button @click="signIn">
41
- Sign In
42
- </Button>
43
- </template>
44
- </template>
45
-
46
- <script setup lang="ts">
47
- import { ref } from 'vue'
48
- import { signMessage } from '@wagmi/core'
49
- import { useConfig, useConnection } from '@wagmi/vue'
50
- import type { Config } from '@wagmi/vue'
51
- import Button from '../../base/components/Button.vue'
52
- import Alert from '../../base/components/Alert.vue'
53
- import Loading from '../../base/components/Loading.vue'
54
- import { createSiweMessage } from '../utils/siwe'
55
- import { useSiwe } from '../composables/siwe'
56
-
57
- type Step = 'idle' | 'signing' | 'verifying' | 'complete' | 'error'
58
-
59
- const props = defineProps<{
60
- getNonce: () => Promise<string>
61
- verify: (message: string, signature: string) => Promise<boolean>
62
- domain?: string
63
- statement?: string
64
- uri?: string
65
- resources?: string[]
66
- requestId?: string
67
- expirationTime?: string
68
- }>()
69
-
70
- const emit = defineEmits<{
71
- authenticated: [{ address: `0x${string}`; chainId: number }]
72
- error: [error: string]
73
- }>()
74
-
75
- function isUserRejection(e: unknown): boolean {
76
- const re = /reject|denied|cancel/i
77
- let current = e as Record<string, unknown> | undefined
78
- while (current) {
79
- if ((current as { code?: number }).code === 4001) return true
80
- if (re.test((current as { details?: string }).details || '')) return true
81
- if (re.test((current as { message?: string }).message || '')) return true
82
- current = current.cause as Record<string, unknown> | undefined
83
- }
84
- return false
85
- }
86
-
87
- const config = useConfig()
88
- const { address, chainId, connector } = useConnection()
89
- const { setSession } = useSiwe()
90
-
91
- const step = ref<Step>('idle')
92
- const errorMessage = ref('')
93
-
94
- const signIn = async () => {
95
- const currentAddress = address.value
96
- const currentChainId = chainId.value
97
-
98
- if (!currentAddress || !currentChainId) {
99
- errorMessage.value = 'Wallet not connected.'
100
- step.value = 'error'
101
- emit('error', errorMessage.value)
102
- return
103
- }
104
-
105
- errorMessage.value = ''
106
-
107
- // Get nonce
108
- let nonce: string
109
- try {
110
- nonce = await props.getNonce()
111
- } catch {
112
- errorMessage.value = 'Failed to get authentication nonce.'
113
- step.value = 'error'
114
- emit('error', errorMessage.value)
115
- return
116
- }
117
-
118
- // Sign message
119
- step.value = 'signing'
120
- const message = createSiweMessage({
121
- domain: props.domain || window.location.host,
122
- address: currentAddress,
123
- uri: props.uri || window.location.origin,
124
- chainId: currentChainId,
125
- nonce,
126
- statement: props.statement,
127
- expirationTime: props.expirationTime,
128
- requestId: props.requestId,
129
- resources: props.resources,
130
- })
131
-
132
- let signature: string
133
- try {
134
- signature = await signMessage(config as Config, { message })
135
- } catch (e: unknown) {
136
- if (isUserRejection(e)) {
137
- errorMessage.value = 'Signature rejected by user.'
138
- } else {
139
- const err = e as { shortMessage?: string; message?: string }
140
- errorMessage.value = err.shortMessage || err.message || 'Failed to sign message.'
141
- }
142
- step.value = 'error'
143
- emit('error', errorMessage.value)
144
- console.error('SIWE signing error:', e)
145
- return
146
- }
147
-
148
- // Verify with backend
149
- step.value = 'verifying'
150
- try {
151
- const verified = await props.verify(message, signature)
152
-
153
- if (!verified) {
154
- throw new Error('Signature verification failed')
155
- }
156
- } catch (e: unknown) {
157
- const err = e as { message?: string }
158
- errorMessage.value = err.message || 'Verification failed.'
159
- step.value = 'error'
160
- emit('error', errorMessage.value)
161
- console.error('SIWE verification error:', e)
162
- return
163
- }
164
-
165
- // Update shared authentication state
166
- setSession({
167
- address: currentAddress,
168
- chainId: currentChainId,
169
- })
170
-
171
- step.value = 'complete'
172
- emit('authenticated', {
173
- address: currentAddress,
174
- chainId: currentChainId,
175
- })
176
- }
177
-
178
- const reset = () => {
179
- step.value = 'idle'
180
- errorMessage.value = ''
181
- }
182
-
183
- defineExpose({ reset })
184
- </script>
185
-
186
- <style scoped>
187
- .secondary {
188
- margin-top: var(--spacer-sm);
189
- }
190
- </style>
@@ -1,93 +0,0 @@
1
- <template>
2
- <Button
3
- v-if="!isAuthenticated"
4
- @click="open = true"
5
- :class="className"
6
- >
7
- <slot>Sign In</slot>
8
- </Button>
9
- <slot
10
- v-else
11
- name="authenticated"
12
- :address="session?.address"
13
- :sign-out="handleSignOut"
14
- >
15
- <Button
16
- @click="handleSignOut"
17
- :class="className"
18
- >Sign Out</Button>
19
- </slot>
20
-
21
- <Dialog
22
- v-if="!isAuthenticated"
23
- title="Sign In with Ethereum"
24
- v-model:open="open"
25
- @closed="onClosed"
26
- >
27
- <EvmSiwe
28
- ref="siweRef"
29
- :get-nonce="getNonce"
30
- :verify="verify"
31
- :domain="domain"
32
- :statement="statement"
33
- :uri="uri"
34
- :resources="resources"
35
- :request-id="requestId"
36
- :expiration-time="expirationTime"
37
- @authenticated="onAuthenticated"
38
- @error="(e) => emit('error', e)"
39
- />
40
- </Dialog>
41
- </template>
42
-
43
- <script setup lang="ts">
44
- import { ref, watch } from 'vue'
45
- import Button from '../../base/components/Button.vue'
46
- import Dialog from '../../base/components/Dialog.vue'
47
- import EvmSiwe from './EvmSiwe.vue'
48
- import { useSiwe } from '../composables/siwe'
49
-
50
- const props = defineProps<{
51
- className?: string
52
- getNonce: () => Promise<string>
53
- verify: (message: string, signature: string) => Promise<boolean>
54
- domain?: string
55
- statement?: string
56
- uri?: string
57
- resources?: string[]
58
- requestId?: string
59
- expirationTime?: string
60
- }>()
61
-
62
- const emit = defineEmits<{
63
- authenticated: [{ address: `0x${string}`; chainId: number }]
64
- signedOut: []
65
- error: [error: string]
66
- }>()
67
-
68
- const { isAuthenticated, session, signOut } = useSiwe()
69
-
70
- const open = ref(false)
71
- const siweRef = ref<InstanceType<typeof EvmSiwe> | null>(null)
72
-
73
- const onAuthenticated = (data: { address: `0x${string}`; chainId: number }) => {
74
- open.value = false
75
- emit('authenticated', data)
76
- }
77
-
78
- const onClosed = () => {
79
- siweRef.value?.reset()
80
- }
81
-
82
- const handleSignOut = () => {
83
- signOut()
84
- emit('signedOut')
85
- }
86
-
87
- watch(isAuthenticated, (authenticated) => {
88
- if (!authenticated) {
89
- open.value = false
90
- siweRef.value?.reset()
91
- }
92
- })
93
- </script>
@@ -1,132 +0,0 @@
1
- <template>
2
- <template v-if="chains.length > 1">
3
- <Button
4
- @click="dialogOpen = true"
5
- :class="className"
6
- >
7
- <slot :current-chain="currentChain">
8
- {{ currentChain?.name || 'Unknown Network' }}
9
- </slot>
10
- </Button>
11
-
12
- <Dialog
13
- title="Switch Network"
14
- v-model:open="dialogOpen"
15
- @closed="onClosed"
16
- compat
17
- >
18
- <Alert
19
- v-if="errorMessage"
20
- type="error"
21
- >
22
- {{ errorMessage }}
23
- </Alert>
24
-
25
- <Loading
26
- v-if="switching"
27
- spinner
28
- stacked
29
- :txt="`Switching to ${switchingTo}...`"
30
- />
31
-
32
- <div
33
- v-if="!switching"
34
- class="chain-list"
35
- >
36
- <Button
37
- v-for="chain in chains"
38
- :key="chain.id"
39
- :disabled="chain.id === currentChainId || undefined"
40
- :class="['block', 'chain-item', { active: chain.id === currentChainId }]"
41
- @click="() => switchTo(chain)"
42
- >
43
- <span>{{ chain.name }}</span>
44
- <Icon
45
- v-if="chain.id === currentChainId"
46
- type="check"
47
- />
48
- </Button>
49
- </div>
50
- </Dialog>
51
- </template>
52
- </template>
53
-
54
- <script setup lang="ts">
55
- import { ref, computed } from 'vue'
56
- import type { Chain } from 'viem'
57
- import { useConfig, useConnection, useSwitchChain } from '@wagmi/vue'
58
- import Button from '../../base/components/Button.vue'
59
- import Dialog from '../../base/components/Dialog.vue'
60
- import Icon from '../../base/components/Icon.vue'
61
- import Alert from '../../base/components/Alert.vue'
62
- import Loading from '../../base/components/Loading.vue'
63
-
64
- defineProps<{
65
- className?: string
66
- }>()
67
-
68
- const emit = defineEmits<{
69
- switched: [{ chainId: number; name: string }]
70
- error: [{ message: string }]
71
- }>()
72
-
73
- const config = useConfig()
74
- const { chainId: currentChainId } = useConnection()
75
- const { mutateAsync: switchChainAsync } = useSwitchChain()
76
-
77
- const chains = computed<readonly Chain[]>(() => config.chains)
78
- const currentChain = computed(() =>
79
- chains.value.find((c) => c.id === currentChainId.value),
80
- )
81
-
82
- const dialogOpen = ref(false)
83
- const switching = ref(false)
84
- const switchingTo = ref('')
85
- const errorMessage = ref('')
86
-
87
- const switchTo = async (chain: Chain) => {
88
- if (chain.id === currentChainId.value) return
89
-
90
- switching.value = true
91
- switchingTo.value = chain.name
92
- errorMessage.value = ''
93
-
94
- try {
95
- await switchChainAsync({ chainId: chain.id })
96
- emit('switched', { chainId: chain.id, name: chain.name })
97
- dialogOpen.value = false
98
- } catch (e: unknown) {
99
- const message = e instanceof Error ? e.message : 'Failed to switch network.'
100
- errorMessage.value =
101
- message.includes('rejected') || message.includes('denied')
102
- ? 'Network switch cancelled.'
103
- : 'Failed to switch network. Please try again.'
104
- emit('error', { message: errorMessage.value })
105
- } finally {
106
- switching.value = false
107
- switchingTo.value = ''
108
- }
109
- }
110
-
111
- const onClosed = () => {
112
- switching.value = false
113
- switchingTo.value = ''
114
- errorMessage.value = ''
115
- }
116
- </script>
117
-
118
- <style scoped>
119
- .chain-list {
120
- display: grid;
121
- gap: var(--spacer-sm);
122
- }
123
-
124
- .chain-item {
125
- justify-content: space-between;
126
-
127
- &.active {
128
- pointer-events: none;
129
- opacity: 1;
130
- }
131
- }
132
- </style>