@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: '
|
|
4
|
+
defaultChain: 'sepolia',
|
|
5
5
|
chains: {
|
|
6
|
-
|
|
7
|
-
id:
|
|
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
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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:
|
|
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
|
|
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
|
|
9
|
+
<slot
|
|
10
|
+
v-else
|
|
11
|
+
name="connected"
|
|
12
|
+
:address="address"
|
|
13
|
+
>
|
|
6
14
|
<EvmAccount :address="address" />
|
|
7
15
|
</slot>
|
|
8
16
|
|
|
9
|
-
<
|
|
10
|
-
|
|
11
|
-
|
|
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
|
|
15
|
-
|
|
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
|
|
38
|
+
<Loading
|
|
39
|
+
txt="Waiting for wallet confirmation..."
|
|
40
|
+
spinner
|
|
41
|
+
stacked
|
|
42
|
+
/>
|
|
18
43
|
</template>
|
|
19
|
-
<div
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
115
|
+
new Map(
|
|
116
|
+
connectors?.map((connector) => [connector.name, connector]),
|
|
117
|
+
).values(),
|
|
70
118
|
)
|
|
71
119
|
|
|
72
|
-
const filtered =
|
|
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 (
|
|
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
|
|
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
|
-
|
|
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
|
-
:
|
|
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
|
-
|
|
21
|
+
stacked
|
|
22
|
+
:txt="text.lead[step] || ''"
|
|
23
23
|
/>
|
|
24
24
|
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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="
|
|
48
|
+
class="link muted small centered"
|
|
40
49
|
>
|
|
41
|
-
|
|
50
|
+
<Icon type="link" />
|
|
51
|
+
<span>View on Block Explorer</span>
|
|
42
52
|
</Button>
|
|
43
53
|
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
<
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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)
|
|
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
|
-
|
|
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.
|
|
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.
|
|
13
|
+
"@1001-digital/layers.base": "^0.0.19"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"@1001-digital/layers.base": "^0.0.
|
|
16
|
+
"@1001-digital/layers.base": "^0.0.19"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@types/qrcode": "^1.5.6",
|