@1001-digital/layers.evm 1.0.1 → 1.0.2

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.
@@ -1,11 +1,11 @@
1
1
  export default defineAppConfig({
2
2
  evm: {
3
3
  title: 'EVM Layer Playground',
4
- defaultChain: 'mainnet',
4
+ defaultChain: 'sepolia',
5
5
  chains: {
6
- mainnet: {
7
- id: 1,
8
- blockExplorer: 'https://etherscan.io',
6
+ sepolia: {
7
+ id: 11155111,
8
+ blockExplorer: 'https://sepolia.etherscan.io',
9
9
  },
10
10
  },
11
11
  },
@@ -14,26 +14,32 @@
14
14
  <h2>Transaction Flow Example</h2>
15
15
  <p>Send 0 ETH to your own address</p>
16
16
 
17
- <EvmTransactionFlow :request="sendTransaction" :text="{
18
- title: {
19
- confirm: 'Send Transaction',
20
- requesting: 'Requesting...',
21
- waiting: 'Waiting for confirmation...',
22
- complete: 'Transaction Complete!',
23
- error: 'Transaction Error',
24
- },
25
- lead: {
26
- confirm: 'This will send 0 ETH to your address as a test transaction.',
27
- requesting: 'Please confirm the transaction in your wallet.',
28
- waiting: 'Your transaction is being processed...',
29
- complete: 'Your transaction has been confirmed on-chain.',
30
- error: 'An error occurred while processing your transaction.',
31
- },
32
- action: {
33
- confirm: 'Send Transaction',
34
- error: 'Try Again',
35
- },
36
- }" @complete="onTransactionComplete" @cancel="onTransactionCancel">
17
+ <EvmTransactionFlow
18
+ :request="sendTransaction"
19
+ :text="{
20
+ title: {
21
+ confirm: 'Send Transaction',
22
+ requesting: 'Requesting...',
23
+ waiting: 'Waiting for confirmation...',
24
+ complete: 'Transaction Complete!',
25
+ error: 'Transaction Error',
26
+ },
27
+ lead: {
28
+ confirm:
29
+ 'This will send 0 ETH to your address as a test transaction.',
30
+ requesting: 'Please confirm the transaction in your wallet.',
31
+ waiting: 'Your transaction is being processed...',
32
+ complete: 'Your transaction has been confirmed on-chain.',
33
+ error: 'An error occurred while processing your transaction.',
34
+ },
35
+ action: {
36
+ confirm: 'Send Transaction',
37
+ error: 'Try Again',
38
+ },
39
+ }"
40
+ @complete="onTransactionComplete"
41
+ @cancel="onTransactionCancel"
42
+ >
37
43
  <template #start="{ start }">
38
44
  <Actions>
39
45
  <Button @click="start">Start Transaction</Button>
@@ -47,10 +53,6 @@
47
53
  <p><strong>Chain:</strong> {{ chainId }}</p>
48
54
  </div>
49
55
  </template>
50
-
51
- <template #complete>
52
- <p class="success">Transaction confirmed successfully!</p>
53
- </template>
54
56
  </EvmTransactionFlow>
55
57
  </Card>
56
58
  </template>
@@ -1,12 +1,19 @@
1
1
  import { fileURLToPath } from 'node:url'
2
2
 
3
+ const layerDir = fileURLToPath(new URL('..', import.meta.url))
4
+
3
5
  export default defineNuxtConfig({
4
6
  extends: ['@1001-digital/layers.base', '..'],
5
7
  modules: ['@nuxt/eslint'],
6
8
  eslint: {
7
9
  config: {
8
10
  // Use the generated ESLint config for lint root project as well
9
- rootDir: fileURLToPath(new URL('..', import.meta.url))
11
+ rootDir: layerDir,
10
12
  }
11
- }
13
+ },
14
+ hooks: {
15
+ 'vite:serverCreated': (server) => {
16
+ server.watcher.add(layerDir)
17
+ },
18
+ },
12
19
  })
@@ -1,35 +1,81 @@
1
1
  <template>
2
- <Button v-if="showConnect" @click="chooseModalOpen = true" :class="className">
2
+ <Button
3
+ v-if="showConnect"
4
+ @click="chooseModalOpen = true"
5
+ :class="className"
6
+ >
3
7
  <slot>Connect Wallet</slot>
4
8
  </Button>
5
- <slot v-else name="connected" :address="address">
9
+ <slot
10
+ v-else
11
+ name="connected"
12
+ :address="address"
13
+ >
6
14
  <EvmAccount :address="address" />
7
15
  </slot>
8
16
 
9
- <Teleport to="body">
10
- <Dialog v-if="showConnect" title="Connect Wallet" v-model:open="chooseModalOpen" @closed="onModalClosed">
11
- <Alert v-if="errorMessage" type="error">
17
+ <Dialog
18
+ v-if="showConnect"
19
+ title="Connect Wallet"
20
+ v-model:open="chooseModalOpen"
21
+ @closed="onModalClosed"
22
+ >
23
+ <Alert
24
+ v-if="errorMessage"
25
+ type="error"
26
+ >
12
27
  {{ errorMessage }}
13
28
  </Alert>
14
- <EvmWalletConnectQR v-if="walletConnectUri" :uri="walletConnectUri" />
15
- <EvmMetaMaskQR v-else-if="metaMaskUri" :uri="metaMaskUri" />
29
+ <EvmWalletConnectQR
30
+ v-if="walletConnectUri"
31
+ :uri="walletConnectUri"
32
+ />
33
+ <EvmMetaMaskQR
34
+ v-else-if="metaMaskUri"
35
+ :uri="metaMaskUri"
36
+ />
16
37
  <template v-else-if="isConnecting">
17
- <Loading txt="Waiting for wallet confirmation..." spinner />
38
+ <Loading
39
+ txt="Waiting for wallet confirmation..."
40
+ spinner
41
+ stacked
42
+ />
18
43
  </template>
19
- <div v-else class="wallet-options">
20
- <Button v-for="connector in shownConnectors" :key="connector.uid" @click="() => login(connector)"
21
- class="choose-connector">
22
- <img v-if="ICONS[connector.name]" :src="connector.icon || `${base}icons/wallets/${ICONS[connector.name]}`"
23
- :alt="connector.name" />
44
+ <div
45
+ v-else
46
+ class="wallet-options"
47
+ >
48
+ <Button
49
+ v-for="connector in shownConnectors"
50
+ :key="connector.uid"
51
+ @click="() => login(connector)"
52
+ class="choose-connector"
53
+ >
54
+ <img
55
+ v-if="ICONS[connector.name]"
56
+ :src="
57
+ connector.icon || `${base}icons/wallets/${ICONS[connector.name]}`
58
+ "
59
+ :alt="connector.name"
60
+ />
61
+ <div
62
+ v-else
63
+ class="default-wallet-icon"
64
+ >
65
+ <Icon type="wallet" />
66
+ </div>
24
67
  <span>{{ connector.name }}</span>
25
68
  </Button>
26
- <Button to="https://ethereum.org/wallets/" target="_blank" class="link muted small">
69
+ <Button
70
+ to="https://ethereum.org/wallets/"
71
+ target="_blank"
72
+ class="link muted small"
73
+ >
27
74
  <Icon type="help" />
28
75
  <span>New to wallets?</span>
29
76
  </Button>
30
77
  </div>
31
- </Dialog>
32
- </Teleport>
78
+ </Dialog>
33
79
  </template>
34
80
 
35
81
  <script setup lang="ts">
@@ -46,7 +92,7 @@ const ICONS: Record<string, string> = {
46
92
  }
47
93
 
48
94
  const PRIORITY: Record<string, number> = {
49
- 'WalletConnect': 20,
95
+ WalletConnect: 20,
50
96
  'Coinbase Wallet': 10,
51
97
  }
52
98
 
@@ -66,10 +112,13 @@ const { address, isConnected } = useConnection()
66
112
  const showConnect = computed(() => !isConnected.value)
67
113
  const shownConnectors = computed(() => {
68
114
  const unique = Array.from(
69
- new Map(connectors?.map((connector) => [connector.name, connector])).values(),
115
+ new Map(
116
+ connectors?.map((connector) => [connector.name, connector]),
117
+ ).values(),
70
118
  )
71
119
 
72
- const filtered = unique.length > 1 ? unique.filter((c) => c.id !== 'injected') : unique
120
+ const filtered =
121
+ unique.length > 1 ? unique.filter((c) => c.id !== 'injected') : unique
73
122
 
74
123
  return filtered.sort((a, b) => {
75
124
  const priorityA = PRIORITY[a.name] ?? 5
@@ -119,7 +168,11 @@ const login = async (connector: Connector) => {
119
168
  metaMaskUri.value = ''
120
169
 
121
170
  const errorMsg = error instanceof Error ? error.message : ''
122
- if (errorMsg.includes('User rejected') || errorMsg.includes('rejected') || errorMsg.includes('denied')) {
171
+ if (
172
+ errorMsg.includes('User rejected') ||
173
+ errorMsg.includes('rejected') ||
174
+ errorMsg.includes('denied')
175
+ ) {
123
176
  errorMessage.value = 'Connection cancelled. Please try again.'
124
177
  } else {
125
178
  errorMessage.value = 'Failed to connect. Please try again.'
@@ -140,7 +193,9 @@ const onModalClosed = () => {
140
193
  }
141
194
 
142
195
  const check = () =>
143
- isConnected.value ? emit('connected', { address: address.value }) : emit('disconnected')
196
+ isConnected.value
197
+ ? emit('connected', { address: address.value })
198
+ : emit('disconnected')
144
199
  watch(isConnected, () => check())
145
200
  onMounted(() => check())
146
201
  </script>
@@ -155,18 +210,25 @@ onMounted(() => check())
155
210
  inline-size: auto;
156
211
  justify-content: flex-start;
157
212
 
158
- img {
213
+ img,
214
+ .default-wallet-icon {
159
215
  margin: -1rem 0 -1rem -0.6rem;
160
216
  width: var(--size-5);
161
217
  height: var(--size-5);
162
218
  }
163
219
 
164
- span {
220
+ .default-wallet-icon {
221
+ display: flex;
222
+ align-items: center;
223
+ justify-content: center;
224
+ background: var(--gray-z-2);
225
+ }
226
+
227
+ span:last-child {
165
228
  border-left: var(--border);
166
229
  padding-left: var(--spacer-sm);
167
230
  }
168
231
  }
169
-
170
232
  }
171
233
 
172
234
  .link.muted {
@@ -8,57 +8,82 @@
8
8
 
9
9
  <Dialog
10
10
  v-model:open="open"
11
- :x-close="canDismiss"
11
+ :closable="canDismiss"
12
12
  :click-outside="canDismiss"
13
+ :title="text.title[step]"
13
14
  class="transaction-flow"
14
15
  >
15
16
  <slot name="before" />
16
17
 
17
- <h1 v-if="text.title[step]">{{ text.title[step] }}</h1>
18
-
19
18
  <Loading
20
19
  v-if="step === 'requesting' || step === 'waiting'"
21
20
  spinner
22
- txt=""
21
+ stacked
22
+ :txt="text.lead[step] || ''"
23
23
  />
24
24
 
25
- <div class="text">
26
- <p v-if="text.lead[step]">{{ text.lead[step] }}</p>
27
- <p v-if="error">{{ error }}</p>
28
- </div>
25
+ <p
26
+ v-if="
27
+ step !== 'requesting' &&
28
+ step !== 'waiting' &&
29
+ step !== 'error' &&
30
+ text.lead[step]
31
+ "
32
+ >
33
+ {{ text.lead[step] }}
34
+ </p>
29
35
 
30
- <slot
31
- :name="step"
32
- :cancel="cancel"
33
- ></slot>
36
+ <Alert
37
+ v-if="error"
38
+ type="error"
39
+ >
40
+ <p v-if="text.lead[step]">{{ text.lead[step] }}</p>
41
+ <p>{{ error }}</p>
42
+ </Alert>
34
43
 
35
44
  <Button
36
45
  v-if="step === 'waiting'"
37
46
  :to="txLink"
38
47
  target="_blank"
39
- class="block-explorer"
48
+ class="link muted small centered"
40
49
  >
41
- View on Block Explorer
50
+ <Icon type="link" />
51
+ <span>View on Block Explorer</span>
42
52
  </Button>
43
53
 
44
- <Actions v-if="step === 'chain'">
45
- <Button
46
- @click="cancel"
47
- class="secondary"
48
- >Cancel</Button
49
- >
50
- </Actions>
51
-
52
- <Actions v-if="step === 'confirm' || step === 'error'">
53
- <Button
54
- @click="cancel"
55
- class="secondary"
56
- >Cancel</Button
57
- >
58
- <Button @click="() => initializeRequest()">
59
- {{ text.action[step] || 'Execute' }}
60
- </Button>
61
- </Actions>
54
+ <slot
55
+ :name="step"
56
+ :cancel="cancel"
57
+ ></slot>
58
+
59
+ <template #footer>
60
+ <template v-if="step === 'chain'">
61
+ <Button
62
+ @click="cancel"
63
+ class="secondary"
64
+ >Cancel</Button
65
+ >
66
+ </template>
67
+
68
+ <template v-if="step === 'confirm' || step === 'error'">
69
+ <Button
70
+ @click="cancel"
71
+ class="secondary"
72
+ >Cancel</Button
73
+ >
74
+ <Button @click="() => initializeRequest()">
75
+ {{ text.action[step] || 'Execute' }}
76
+ </Button>
77
+ </template>
78
+
79
+ <slot
80
+ name="actions"
81
+ :step="step"
82
+ :cancel="cancel"
83
+ :execute="() => initializeRequest()"
84
+ :tx-link="txLink"
85
+ />
86
+ </template>
62
87
  </Dialog>
63
88
  </template>
64
89
 
@@ -82,6 +107,7 @@ type Step =
82
107
  | 'complete'
83
108
  | 'error'
84
109
 
110
+ const slots = useSlots()
85
111
  const checkChain = useEnsureChainIdCheck()
86
112
 
87
113
  const { $wagmi } = useNuxtApp()
@@ -127,7 +153,10 @@ const step = ref<Step>('idle')
127
153
  const open = computed({
128
154
  get: () => step.value !== 'idle',
129
155
  set: (v) => {
130
- if (!v) step.value = 'idle'
156
+ if (!v) {
157
+ step.value = 'idle'
158
+ error.value = ''
159
+ }
131
160
  },
132
161
  })
133
162
 
@@ -187,7 +216,8 @@ const initializeRequest = async (request = cachedRequest.value) => {
187
216
  } catch (e: unknown) {
188
217
  const err = e as { cause?: { code?: number }; shortMessage?: string }
189
218
  if (err?.cause?.code === 4001) {
190
- step.value = 'idle'
219
+ error.value = 'Transaction rejected by user.'
220
+ step.value = 'error'
191
221
  } else {
192
222
  error.value = err.shortMessage || 'Error submitting transaction request.'
193
223
  step.value = 'error'
@@ -215,6 +245,7 @@ const start = () => {
215
245
 
216
246
  const cancel = () => {
217
247
  step.value = 'idle'
248
+ error.value = ''
218
249
  emit('cancel')
219
250
  }
220
251
 
@@ -224,7 +255,7 @@ defineExpose({
224
255
  </script>
225
256
 
226
257
  <style>
227
- .transaction-flow {
258
+ .transaction-flow > section {
228
259
  display: grid;
229
260
  gap: var(--spacer);
230
261
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@1001-digital/layers.evm",
3
3
  "type": "module",
4
- "version": "1.0.1",
4
+ "version": "1.0.2",
5
5
  "main": "./nuxt.config.ts",
6
6
  "devDependencies": {
7
7
  "@nuxt/eslint": "latest",
@@ -10,10 +10,10 @@
10
10
  "nuxt": "^4.3.0",
11
11
  "typescript": "^5.9.3",
12
12
  "vue": "latest",
13
- "@1001-digital/layers.base": "^0.0.17"
13
+ "@1001-digital/layers.base": "^0.0.19"
14
14
  },
15
15
  "peerDependencies": {
16
- "@1001-digital/layers.base": "^0.0.17"
16
+ "@1001-digital/layers.base": "^0.0.19"
17
17
  },
18
18
  "dependencies": {
19
19
  "@types/qrcode": "^1.5.6",