@1001-digital/layers.evm 0.0.7 → 1.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/.env.example +4 -0
- package/.playground/app/app.config.ts +10 -3
- package/AGENTS.md +24 -10
- package/app/app.config.ts +20 -4
- package/app/components/EvmTransactionFlow.vue +130 -106
- package/app/composables/chainId.ts +20 -3
- package/app/plugins/wagmi.ts +32 -25
- package/app/utils/chains.ts +13 -0
- package/nuxt.config.ts +6 -7
- package/package.json +4 -3
- package/.playground/.env.example +0 -7
package/.env.example
ADDED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
export default defineAppConfig({
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
evm: {
|
|
3
|
+
title: 'EVM Layer Playground',
|
|
4
|
+
defaultChain: 'mainnet',
|
|
5
|
+
chains: {
|
|
6
|
+
mainnet: {
|
|
7
|
+
id: 1,
|
|
8
|
+
blockExplorer: 'https://etherscan.io',
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
},
|
|
5
12
|
})
|
package/AGENTS.md
CHANGED
|
@@ -22,7 +22,7 @@ Uses modern wagmi 0.4.x patterns:
|
|
|
22
22
|
- `useConnectionEffect` (not deprecated `useAccountEffect`)
|
|
23
23
|
- `useSwitchConnection` (not deprecated `useSwitchAccount`)
|
|
24
24
|
|
|
25
|
-
Configured chains: mainnet, sepolia, holesky, localhost
|
|
25
|
+
Configured chains: resolved dynamically from `app.config.ts` via `evm.chains` map (supports mainnet, sepolia, holesky, optimism, arbitrum, base, polygon, localhost out of the box)
|
|
26
26
|
|
|
27
27
|
Connectors: injected, coinbaseWallet, metaMask, walletConnect
|
|
28
28
|
|
|
@@ -37,7 +37,9 @@ Connectors: injected, coinbaseWallet, metaMask, walletConnect
|
|
|
37
37
|
|
|
38
38
|
## Composables
|
|
39
39
|
|
|
40
|
-
- `
|
|
40
|
+
- `useChainConfig(key?)` - Get `{ id, blockExplorer }` for a named chain (defaults to `defaultChain`)
|
|
41
|
+
- `useMainChainId()` - Get main chain ID from app config
|
|
42
|
+
- `useBlockExplorer(key?)` - Get block explorer URL for a named chain
|
|
41
43
|
- `useEnsureChainIdCheck()` - Validate/switch chain before transactions
|
|
42
44
|
- `useBaseURL()` - Get base URL with trailing slash
|
|
43
45
|
- `useClipboard()` - Copy text to clipboard with copied state
|
|
@@ -46,17 +48,29 @@ Connectors: injected, coinbaseWallet, metaMask, walletConnect
|
|
|
46
48
|
|
|
47
49
|
- `shortAddress(address, length)` - Truncate address for display
|
|
48
50
|
- `formatETH(value, maxDecimals)` - Format ETH values
|
|
51
|
+
- `resolveChain(id)` - Resolve chain ID to viem Chain object
|
|
49
52
|
|
|
50
|
-
##
|
|
53
|
+
## Configuration
|
|
54
|
+
|
|
55
|
+
Static chain config lives in `app.config.ts` (safe to commit):
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
evm: {
|
|
59
|
+
title: 'My dApp',
|
|
60
|
+
defaultChain: 'mainnet',
|
|
61
|
+
chains: {
|
|
62
|
+
mainnet: { id: 1, blockExplorer: 'https://etherscan.io' },
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Sensitive RPC URLs live in `runtimeConfig.public.evm` (env-driven):
|
|
51
68
|
|
|
52
69
|
```bash
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
NUXT_PUBLIC_RPC2=""
|
|
58
|
-
NUXT_PUBLIC_RPC3=""
|
|
59
|
-
NUXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=""
|
|
70
|
+
NUXT_PUBLIC_EVM_WALLET_CONNECT_PROJECT_ID=""
|
|
71
|
+
NUXT_PUBLIC_EVM_CHAINS_MAINNET_RPC1=""
|
|
72
|
+
NUXT_PUBLIC_EVM_CHAINS_MAINNET_RPC2=""
|
|
73
|
+
NUXT_PUBLIC_EVM_CHAINS_MAINNET_RPC3=""
|
|
60
74
|
```
|
|
61
75
|
|
|
62
76
|
## Key directories
|
package/app/app.config.ts
CHANGED
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
export default defineAppConfig({
|
|
2
2
|
evm: {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
title: 'EVM Layer',
|
|
4
|
+
defaultChain: 'mainnet',
|
|
5
|
+
chains: {
|
|
6
|
+
mainnet: {
|
|
7
|
+
id: 1,
|
|
8
|
+
blockExplorer: 'https://etherscan.io',
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
},
|
|
5
12
|
})
|
|
6
13
|
|
|
14
|
+
interface EvmChainConfig {
|
|
15
|
+
id?: number
|
|
16
|
+
blockExplorer?: string
|
|
17
|
+
}
|
|
18
|
+
|
|
7
19
|
declare module '@nuxt/schema' {
|
|
8
20
|
interface AppConfigInput {
|
|
9
21
|
evm?: {
|
|
10
|
-
/**
|
|
11
|
-
|
|
22
|
+
/** App title */
|
|
23
|
+
title?: string
|
|
24
|
+
/** Key into `chains` that serves as the app's primary chain */
|
|
25
|
+
defaultChain?: string
|
|
26
|
+
/** Named chain definitions */
|
|
27
|
+
chains?: Record<string, EvmChainConfig>
|
|
12
28
|
}
|
|
13
29
|
}
|
|
14
30
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<slot :start="start" name="start"></slot>
|
|
3
|
-
|
|
4
|
-
<Dialog
|
|
2
|
+
<slot :start="start" :step="step" :open="open" name="start"></slot>
|
|
3
|
+
|
|
4
|
+
<Dialog
|
|
5
|
+
v-model:open="open"
|
|
6
|
+
:x-close="canDismiss"
|
|
7
|
+
:click-outside="canDismiss"
|
|
8
|
+
class="transaction-flow"
|
|
9
|
+
>
|
|
5
10
|
<slot name="before" />
|
|
6
11
|
|
|
7
12
|
<h1 v-if="text.title[step]">{{ text.title[step] }}</h1>
|
|
@@ -13,7 +18,12 @@
|
|
|
13
18
|
|
|
14
19
|
<slot :name="step" :cancel="cancel"></slot>
|
|
15
20
|
|
|
16
|
-
<Button
|
|
21
|
+
<Button
|
|
22
|
+
v-if="step === 'waiting'"
|
|
23
|
+
:to="txLink"
|
|
24
|
+
target="_blank"
|
|
25
|
+
class="block-explorer"
|
|
26
|
+
>
|
|
17
27
|
<Icon type="loader" class="spin" />
|
|
18
28
|
<span>View on Block Explorer</span>
|
|
19
29
|
</Button>
|
|
@@ -24,85 +34,95 @@
|
|
|
24
34
|
|
|
25
35
|
<Actions v-if="step === 'confirm' || step === 'error'">
|
|
26
36
|
<Button @click="cancel" class="secondary">Cancel</Button>
|
|
27
|
-
<Button @click="() => initializeRequest()">{{
|
|
37
|
+
<Button @click="() => initializeRequest()">{{
|
|
38
|
+
text.action[step] || "Execute"
|
|
39
|
+
}}</Button>
|
|
28
40
|
</Actions>
|
|
29
41
|
</Dialog>
|
|
30
42
|
</template>
|
|
31
43
|
|
|
32
44
|
<script setup lang="ts">
|
|
33
|
-
import { waitForTransactionReceipt, watchChainId } from
|
|
34
|
-
import type { Config } from
|
|
35
|
-
import type { TransactionReceipt, Hash } from
|
|
45
|
+
import { waitForTransactionReceipt, watchChainId } from "@wagmi/core";
|
|
46
|
+
import type { Config } from "@wagmi/vue";
|
|
47
|
+
import type { TransactionReceipt, Hash } from "viem";
|
|
36
48
|
|
|
37
49
|
interface TextConfig {
|
|
38
|
-
title: Record<string, string
|
|
39
|
-
lead: Record<string, string
|
|
40
|
-
action: Record<string, string
|
|
50
|
+
title: Record<string, string>;
|
|
51
|
+
lead: Record<string, string>;
|
|
52
|
+
action: Record<string, string>;
|
|
41
53
|
}
|
|
42
54
|
|
|
43
|
-
const checkChain = useEnsureChainIdCheck()
|
|
44
|
-
|
|
45
|
-
const { $wagmi } = useNuxtApp()
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
const props = withDefaults(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
55
|
+
const checkChain = useEnsureChainIdCheck();
|
|
56
|
+
|
|
57
|
+
const { $wagmi } = useNuxtApp();
|
|
58
|
+
const blockExplorer = useBlockExplorer();
|
|
59
|
+
|
|
60
|
+
const props = withDefaults(
|
|
61
|
+
defineProps<{
|
|
62
|
+
text?: TextConfig;
|
|
63
|
+
request?: () => Promise<Hash>;
|
|
64
|
+
delayAfter?: number;
|
|
65
|
+
delayAutoclose?: number;
|
|
66
|
+
skipConfirmation?: boolean;
|
|
67
|
+
autoCloseSuccess?: boolean;
|
|
68
|
+
dismissable?: boolean;
|
|
69
|
+
}>(),
|
|
70
|
+
{
|
|
71
|
+
text: () => ({
|
|
72
|
+
title: {
|
|
73
|
+
confirm: "Confirm Transaction",
|
|
74
|
+
},
|
|
75
|
+
lead: {
|
|
76
|
+
confirm: "Please review and confirm this transaction.",
|
|
77
|
+
},
|
|
78
|
+
action: {
|
|
79
|
+
confirm: "Execute",
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
delayAfter: 2000,
|
|
83
|
+
delayAutoclose: 2000,
|
|
84
|
+
skipConfirmation: false,
|
|
85
|
+
autoCloseSuccess: true,
|
|
86
|
+
dismissable: true,
|
|
87
|
+
},
|
|
88
|
+
);
|
|
72
89
|
|
|
73
90
|
const emit = defineEmits<{
|
|
74
|
-
complete: [receipt: TransactionReceipt]
|
|
75
|
-
cancel: []
|
|
76
|
-
}>()
|
|
91
|
+
complete: [receipt: TransactionReceipt];
|
|
92
|
+
cancel: [];
|
|
93
|
+
}>();
|
|
77
94
|
|
|
78
|
-
const open = ref(false)
|
|
95
|
+
const open = ref(false);
|
|
79
96
|
|
|
80
|
-
const switchChain = ref(false)
|
|
97
|
+
const switchChain = ref(false);
|
|
81
98
|
watchChainId($wagmi as Config, {
|
|
82
99
|
async onChange() {
|
|
83
|
-
if (!switchChain.value) return
|
|
100
|
+
if (!switchChain.value) return;
|
|
84
101
|
|
|
85
102
|
if (await checkChain()) {
|
|
86
|
-
switchChain.value = false
|
|
87
|
-
initializeRequest()
|
|
103
|
+
switchChain.value = false;
|
|
104
|
+
initializeRequest();
|
|
88
105
|
} else {
|
|
89
|
-
switchChain.value = true
|
|
106
|
+
switchChain.value = true;
|
|
90
107
|
}
|
|
91
108
|
},
|
|
92
|
-
})
|
|
109
|
+
});
|
|
93
110
|
|
|
94
|
-
const cachedRequest = ref(props.request)
|
|
95
|
-
watch(
|
|
96
|
-
|
|
97
|
-
|
|
111
|
+
const cachedRequest = ref(props.request);
|
|
112
|
+
watch(
|
|
113
|
+
() => props.request,
|
|
114
|
+
() => {
|
|
115
|
+
cachedRequest.value = props.request;
|
|
116
|
+
},
|
|
117
|
+
);
|
|
98
118
|
|
|
99
|
-
const requesting = ref(false)
|
|
100
|
-
const waiting = ref(false)
|
|
101
|
-
const complete = ref(false)
|
|
102
|
-
const error = ref(
|
|
103
|
-
const tx = ref<Hash | null>(null)
|
|
104
|
-
const receipt = ref<TransactionReceipt | null>(null)
|
|
105
|
-
const txLink = computed(() => `${
|
|
119
|
+
const requesting = ref(false);
|
|
120
|
+
const waiting = ref(false);
|
|
121
|
+
const complete = ref(false);
|
|
122
|
+
const error = ref("");
|
|
123
|
+
const tx = ref<Hash | null>(null);
|
|
124
|
+
const receipt = ref<TransactionReceipt | null>(null);
|
|
125
|
+
const txLink = computed(() => `${blockExplorer}/tx/${tx.value}`);
|
|
106
126
|
|
|
107
127
|
const step = computed(() => {
|
|
108
128
|
if (
|
|
@@ -112,96 +132,100 @@ const step = computed(() => {
|
|
|
112
132
|
!waiting.value &&
|
|
113
133
|
!complete.value
|
|
114
134
|
) {
|
|
115
|
-
return
|
|
135
|
+
return "confirm";
|
|
116
136
|
}
|
|
117
137
|
|
|
118
138
|
if (switchChain.value) {
|
|
119
|
-
return
|
|
139
|
+
return "chain";
|
|
120
140
|
}
|
|
121
141
|
|
|
122
142
|
if (requesting.value) {
|
|
123
|
-
return
|
|
143
|
+
return "requesting";
|
|
124
144
|
}
|
|
125
145
|
|
|
126
146
|
if (waiting.value) {
|
|
127
|
-
return
|
|
147
|
+
return "waiting";
|
|
128
148
|
}
|
|
129
149
|
|
|
130
150
|
if (complete.value) {
|
|
131
|
-
return
|
|
151
|
+
return "complete";
|
|
132
152
|
}
|
|
133
153
|
|
|
134
|
-
return
|
|
135
|
-
})
|
|
154
|
+
return "error";
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
const canDismiss = computed(
|
|
158
|
+
() => props.dismissable && step.value !== "requesting",
|
|
159
|
+
);
|
|
136
160
|
|
|
137
161
|
const initializeRequest = async (request = cachedRequest.value) => {
|
|
138
|
-
cachedRequest.value = request
|
|
139
|
-
complete.value = false
|
|
140
|
-
open.value = true
|
|
141
|
-
error.value =
|
|
142
|
-
tx.value = null
|
|
143
|
-
receipt.value = null
|
|
162
|
+
cachedRequest.value = request;
|
|
163
|
+
complete.value = false;
|
|
164
|
+
open.value = true;
|
|
165
|
+
error.value = "";
|
|
166
|
+
tx.value = null;
|
|
167
|
+
receipt.value = null;
|
|
144
168
|
|
|
145
169
|
if (!(await checkChain())) {
|
|
146
|
-
switchChain.value = true
|
|
147
|
-
return
|
|
170
|
+
switchChain.value = true;
|
|
171
|
+
return;
|
|
148
172
|
} else {
|
|
149
|
-
switchChain.value = false
|
|
173
|
+
switchChain.value = false;
|
|
150
174
|
}
|
|
151
175
|
|
|
152
|
-
if (requesting.value) return
|
|
176
|
+
if (requesting.value) return;
|
|
153
177
|
|
|
154
178
|
try {
|
|
155
|
-
requesting.value = true
|
|
156
|
-
tx.value = await request!()
|
|
157
|
-
requesting.value = false
|
|
158
|
-
waiting.value = true
|
|
179
|
+
requesting.value = true;
|
|
180
|
+
tx.value = await request!();
|
|
181
|
+
requesting.value = false;
|
|
182
|
+
waiting.value = true;
|
|
159
183
|
const [receiptObject] = await Promise.all([
|
|
160
184
|
waitForTransactionReceipt($wagmi as Config, { hash: tx.value }),
|
|
161
|
-
])
|
|
162
|
-
await delay(props.delayAfter)
|
|
163
|
-
receipt.value = receiptObject
|
|
164
|
-
emit(
|
|
165
|
-
complete.value = true
|
|
185
|
+
]);
|
|
186
|
+
await delay(props.delayAfter);
|
|
187
|
+
receipt.value = receiptObject;
|
|
188
|
+
emit("complete", receiptObject);
|
|
189
|
+
complete.value = true;
|
|
166
190
|
} catch (e: unknown) {
|
|
167
|
-
const err = e as { cause?: { code?: number }; shortMessage?: string }
|
|
191
|
+
const err = e as { cause?: { code?: number }; shortMessage?: string };
|
|
168
192
|
if (err?.cause?.code === 4001) {
|
|
169
|
-
open.value = false
|
|
193
|
+
open.value = false;
|
|
170
194
|
} else {
|
|
171
|
-
error.value = err.shortMessage ||
|
|
195
|
+
error.value = err.shortMessage || "Error submitting transaction request.";
|
|
172
196
|
}
|
|
173
|
-
console.log(e)
|
|
197
|
+
console.log(e);
|
|
174
198
|
}
|
|
175
199
|
|
|
176
|
-
requesting.value = false
|
|
177
|
-
waiting.value = false
|
|
200
|
+
requesting.value = false;
|
|
201
|
+
waiting.value = false;
|
|
178
202
|
|
|
179
|
-
if (props.autoCloseSuccess && step.value ===
|
|
180
|
-
await delay(props.delayAutoclose)
|
|
181
|
-
open.value = false
|
|
182
|
-
await delay(300)
|
|
203
|
+
if (props.autoCloseSuccess && step.value === "complete") {
|
|
204
|
+
await delay(props.delayAutoclose);
|
|
205
|
+
open.value = false;
|
|
206
|
+
await delay(300);
|
|
183
207
|
}
|
|
184
208
|
|
|
185
|
-
return receipt.value
|
|
186
|
-
}
|
|
209
|
+
return receipt.value;
|
|
210
|
+
};
|
|
187
211
|
|
|
188
212
|
const start = () => {
|
|
189
213
|
if (props.skipConfirmation && !open.value) {
|
|
190
|
-
initializeRequest()
|
|
214
|
+
initializeRequest();
|
|
191
215
|
}
|
|
192
216
|
|
|
193
|
-
open.value = true
|
|
194
|
-
}
|
|
217
|
+
open.value = true;
|
|
218
|
+
};
|
|
195
219
|
|
|
196
220
|
const cancel = () => {
|
|
197
|
-
open.value = false
|
|
221
|
+
open.value = false;
|
|
198
222
|
|
|
199
|
-
emit(
|
|
200
|
-
}
|
|
223
|
+
emit("cancel");
|
|
224
|
+
};
|
|
201
225
|
|
|
202
226
|
defineExpose({
|
|
203
227
|
initializeRequest,
|
|
204
|
-
})
|
|
228
|
+
});
|
|
205
229
|
</script>
|
|
206
230
|
|
|
207
231
|
<style>
|
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
import { useConnection, useSwitchChain } from '@wagmi/vue'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
interface ChainConfig {
|
|
4
|
+
id?: number
|
|
5
|
+
blockExplorer?: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const getDefaultChainKey = () => useAppConfig().evm?.defaultChain || 'mainnet'
|
|
9
|
+
|
|
10
|
+
export const useChainConfig = (key?: string) => {
|
|
11
|
+
const appConfig = useAppConfig()
|
|
12
|
+
const resolvedKey = key || getDefaultChainKey()
|
|
13
|
+
const chains = appConfig.evm?.chains as Record<string, ChainConfig> | undefined
|
|
14
|
+
const chain = chains?.[resolvedKey]
|
|
5
15
|
|
|
6
|
-
return
|
|
16
|
+
return {
|
|
17
|
+
id: chain?.id ?? 1,
|
|
18
|
+
blockExplorer: chain?.blockExplorer ?? 'https://etherscan.io',
|
|
19
|
+
}
|
|
7
20
|
}
|
|
8
21
|
|
|
22
|
+
export const useMainChainId = () => useChainConfig().id
|
|
23
|
+
|
|
24
|
+
export const useBlockExplorer = (key?: string) => useChainConfig(key).blockExplorer
|
|
25
|
+
|
|
9
26
|
export const useEnsureChainIdCheck = () => {
|
|
10
27
|
const chainId = useMainChainId()
|
|
11
28
|
const { switchChain } = useSwitchChain()
|
package/app/plugins/wagmi.ts
CHANGED
|
@@ -9,14 +9,38 @@ import {
|
|
|
9
9
|
type Config,
|
|
10
10
|
type CreateConnectorFn,
|
|
11
11
|
} from '@wagmi/vue'
|
|
12
|
-
import { mainnet, sepolia, holesky, localhost } from '@wagmi/vue/chains'
|
|
13
12
|
import { coinbaseWallet, injected, metaMask, walletConnect } from '@wagmi/vue/connectors'
|
|
14
|
-
import type {
|
|
13
|
+
import type { Chain, Transport } from 'viem'
|
|
15
14
|
|
|
16
15
|
export default defineNuxtPlugin((nuxtApp) => {
|
|
17
|
-
const
|
|
18
|
-
const
|
|
16
|
+
const appConfig = useAppConfig()
|
|
17
|
+
const runtimeConfig = nuxtApp.$config.public.evm as {
|
|
18
|
+
walletConnectProjectId: string
|
|
19
|
+
chains: Record<string, { rpc1?: string, rpc2?: string, rpc3?: string }>
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const title = appConfig.evm?.title || 'EVM Layer'
|
|
23
|
+
const chainEntries = appConfig.evm?.chains || {}
|
|
24
|
+
|
|
25
|
+
// Build chains and transports from config
|
|
26
|
+
const chains: [Chain, ...Chain[]] = [] as unknown as [Chain, ...Chain[]]
|
|
27
|
+
const transports: Record<number, Transport> = {}
|
|
19
28
|
|
|
29
|
+
for (const [key, entry] of Object.entries(chainEntries)) {
|
|
30
|
+
const chain = resolveChain(entry.id!)
|
|
31
|
+
chains.push(chain)
|
|
32
|
+
|
|
33
|
+
const rpcs = runtimeConfig.chains?.[key]
|
|
34
|
+
const transportList = []
|
|
35
|
+
if (rpcs?.rpc1) transportList.push(http(rpcs.rpc1))
|
|
36
|
+
if (rpcs?.rpc2) transportList.push(http(rpcs.rpc2))
|
|
37
|
+
if (rpcs?.rpc3) transportList.push(http(rpcs.rpc3))
|
|
38
|
+
transportList.push(http())
|
|
39
|
+
|
|
40
|
+
transports[chain.id] = fallback(transportList)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Connectors
|
|
20
44
|
const connectors: CreateConnectorFn[] = [
|
|
21
45
|
injected(),
|
|
22
46
|
coinbaseWallet({
|
|
@@ -33,28 +57,16 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
33
57
|
}),
|
|
34
58
|
]
|
|
35
59
|
|
|
36
|
-
if (import.meta.client &&
|
|
60
|
+
if (import.meta.client && runtimeConfig.walletConnectProjectId)
|
|
37
61
|
connectors.push(
|
|
38
62
|
walletConnect({
|
|
39
|
-
projectId:
|
|
63
|
+
projectId: runtimeConfig.walletConnectProjectId,
|
|
40
64
|
showQrModal: false,
|
|
41
65
|
}),
|
|
42
66
|
)
|
|
43
67
|
|
|
44
|
-
const transportDefinitions: CustomTransport | Transport[] = []
|
|
45
|
-
|
|
46
|
-
if (nuxtApp.$config.public.rpc1)
|
|
47
|
-
transportDefinitions.push(http(nuxtApp.$config.public.rpc1 as string))
|
|
48
|
-
if (nuxtApp.$config.public.rpc2)
|
|
49
|
-
transportDefinitions.push(http(nuxtApp.$config.public.rpc2 as string))
|
|
50
|
-
if (nuxtApp.$config.public.rpc3)
|
|
51
|
-
transportDefinitions.push(http(nuxtApp.$config.public.rpc3 as string))
|
|
52
|
-
transportDefinitions.push(http())
|
|
53
|
-
|
|
54
|
-
const transports = fallback(transportDefinitions)
|
|
55
|
-
|
|
56
68
|
const wagmiConfig: Config = createConfig({
|
|
57
|
-
chains
|
|
69
|
+
chains,
|
|
58
70
|
batch: {
|
|
59
71
|
multicall: true,
|
|
60
72
|
},
|
|
@@ -63,12 +75,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
63
75
|
storage: cookieStorage,
|
|
64
76
|
}),
|
|
65
77
|
ssr: true,
|
|
66
|
-
transports
|
|
67
|
-
[mainnet.id]: mainChainId == 1 ? transports : http(),
|
|
68
|
-
[sepolia.id]: transports,
|
|
69
|
-
[holesky.id]: transports,
|
|
70
|
-
[localhost.id]: transports,
|
|
71
|
-
},
|
|
78
|
+
transports,
|
|
72
79
|
})
|
|
73
80
|
|
|
74
81
|
nuxtApp.vueApp.use(WagmiPlugin, { config: wagmiConfig }).use(VueQueryPlugin, {})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineChain, type Chain } from 'viem'
|
|
2
|
+
import { mainnet, sepolia, holesky, optimism, arbitrum, base, polygon, localhost } from 'viem/chains'
|
|
3
|
+
|
|
4
|
+
const KNOWN: Chain[] = [mainnet, sepolia, holesky, optimism, arbitrum, base, polygon, localhost]
|
|
5
|
+
const byId = new Map<number, Chain>(KNOWN.map(c => [c.id, c]))
|
|
6
|
+
|
|
7
|
+
export const resolveChain = (id: number): Chain =>
|
|
8
|
+
byId.get(id) ?? defineChain({
|
|
9
|
+
id,
|
|
10
|
+
name: `Chain ${id}`,
|
|
11
|
+
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
|
|
12
|
+
rpcUrls: { default: { http: [] } },
|
|
13
|
+
})
|
package/nuxt.config.ts
CHANGED
|
@@ -8,13 +8,12 @@ export default defineNuxtConfig({
|
|
|
8
8
|
|
|
9
9
|
runtimeConfig: {
|
|
10
10
|
public: {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
walletConnectProjectId: '',
|
|
11
|
+
evm: {
|
|
12
|
+
walletConnectProjectId: '',
|
|
13
|
+
chains: {
|
|
14
|
+
mainnet: { rpc1: '', rpc2: '', rpc3: '' },
|
|
15
|
+
},
|
|
16
|
+
},
|
|
18
17
|
},
|
|
19
18
|
},
|
|
20
19
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1001-digital/layers.evm",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"main": "./nuxt.config.ts",
|
|
6
6
|
"devDependencies": {
|
|
7
7
|
"@nuxt/eslint": "latest",
|
|
@@ -10,15 +10,16 @@
|
|
|
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.17"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"@1001-digital/layers.base": "^0.0.
|
|
16
|
+
"@1001-digital/layers.base": "^0.0.17"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@types/qrcode": "^1.5.6",
|
|
20
20
|
"@metamask/sdk": "~0.34.0",
|
|
21
21
|
"@tanstack/vue-query": "^5.92.9",
|
|
22
|
+
"@wagmi/core": "^3.3.2",
|
|
22
23
|
"@wagmi/vue": "^0.4.15",
|
|
23
24
|
"@walletconnect/ethereum-provider": "~2.23.4",
|
|
24
25
|
"qrcode": "^1.5.4",
|