@visualizevalue/mint-app-base 0.1.47 → 0.1.49
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/app.config.ts +12 -0
- package/components/CodeEditor.client.vue +49 -0
- package/components/Collection/Actions.vue +19 -0
- package/components/Collection/Intro.vue +1 -12
- package/components/Embed.vue +33 -0
- package/components/Form/Group.vue +1 -1
- package/components/Form/SelectFile.vue +4 -0
- package/components/Icon.vue +1 -0
- package/components/Mint/Action.client.vue +51 -0
- package/components/Mint/Detail.client.vue +49 -0
- package/components/Mint/Preview.client.vue +58 -0
- package/components/Mint/Renderer/Base.client.vue +107 -0
- package/components/Mint/Renderer/P5.client.vue +67 -0
- package/components/Mint/SelectRenderer.client.vue +52 -0
- package/components/Page/Frame.vue +1 -0
- package/components/Renderer/InstallButton.vue +62 -0
- package/components/Renderer/InstallCustom.client.vue +91 -0
- package/components/Renderer/Overview.client.vue +75 -0
- package/components/Renderer/OverviewCard.vue +32 -0
- package/components/Tabs.vue +37 -0
- package/components/Token/Detail.client.vue +2 -1
- package/components/Token/OverviewCard.vue +2 -1
- package/components/TransactionFlow.vue +5 -3
- package/composables/collections.ts +50 -4
- package/composables/createMint.ts +155 -0
- package/index.d.ts +11 -0
- package/nuxt.config.ts +1 -1
- package/package.json +4 -1
- package/pages/[id]/[collection]/mint.vue +5 -240
- package/pages/[id]/[collection]/renderers.vue +43 -0
- package/utils/abis.ts +6 -1
- package/utils/p5Script.ts +33 -0
- package/utils/types.ts +13 -2
package/app.config.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="code-editor">
|
|
3
|
+
<CodeMirror
|
|
4
|
+
:value="modelValue"
|
|
5
|
+
:options="cmOptions"
|
|
6
|
+
height="100%"
|
|
7
|
+
:placeholder="placeholder"
|
|
8
|
+
@change="$emit('update:modelValue', $event)"
|
|
9
|
+
original-style
|
|
10
|
+
/>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup>
|
|
15
|
+
import CodeMirror from 'codemirror-editor-vue3'
|
|
16
|
+
import 'codemirror/addon/display/placeholder.js'
|
|
17
|
+
import 'codemirror/mode/htmlmixed/htmlmixed.js'
|
|
18
|
+
import 'codemirror/mode/javascript/javascript.js'
|
|
19
|
+
// import 'codemirror/theme/ayu-mirage.css'
|
|
20
|
+
|
|
21
|
+
const props = defineProps({
|
|
22
|
+
modelValue: String,
|
|
23
|
+
placeholder: String,
|
|
24
|
+
mode: {
|
|
25
|
+
type: String,
|
|
26
|
+
default: 'text/javascript'
|
|
27
|
+
},
|
|
28
|
+
})
|
|
29
|
+
const emit = defineEmits(['update:modelValue'])
|
|
30
|
+
|
|
31
|
+
const cmOptions = computed(() => ({
|
|
32
|
+
mode: props.mode,
|
|
33
|
+
// theme: 'ayu-mirage',
|
|
34
|
+
indentUnit: 2,
|
|
35
|
+
tabSize: 2,
|
|
36
|
+
indentWithTab: false
|
|
37
|
+
}))
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<style scoped>
|
|
41
|
+
.code-editor {
|
|
42
|
+
text-transform: none;
|
|
43
|
+
height: 100%;
|
|
44
|
+
|
|
45
|
+
:deep(.CodeMirror) {
|
|
46
|
+
height: 100%;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<menu v-if="ownedByMe">
|
|
3
|
+
<CollectionWithdraw :collection="collection" />
|
|
4
|
+
<Button
|
|
5
|
+
:to="{ name: 'id-collection-mint', params: { id, collection: collection.address } }"
|
|
6
|
+
id="mint-new"
|
|
7
|
+
>
|
|
8
|
+
<Icon type="add" />
|
|
9
|
+
<span>Mint</span>
|
|
10
|
+
</Button>
|
|
11
|
+
</menu>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup>
|
|
15
|
+
const { collection } = defineProps({ collection: Object })
|
|
16
|
+
|
|
17
|
+
const id = useArtistId()
|
|
18
|
+
const ownedByMe = useIsMeCheck(collection.owner)
|
|
19
|
+
</script>
|
|
@@ -26,16 +26,7 @@
|
|
|
26
26
|
</p>
|
|
27
27
|
</div>
|
|
28
28
|
|
|
29
|
-
<
|
|
30
|
-
<CollectionWithdraw :collection="collection" />
|
|
31
|
-
<Button
|
|
32
|
-
:to="{ name: 'id-collection-mint', params: { id, collection: collection.address } }"
|
|
33
|
-
id="mint-new"
|
|
34
|
-
>
|
|
35
|
-
<Icon type="add" />
|
|
36
|
-
<span>Mint New</span>
|
|
37
|
-
</Button>
|
|
38
|
-
</menu>
|
|
29
|
+
<CollectionActions :collection="collection" />
|
|
39
30
|
</div>
|
|
40
31
|
</slot>
|
|
41
32
|
</header>
|
|
@@ -48,8 +39,6 @@ const { collection } = defineProps<{
|
|
|
48
39
|
|
|
49
40
|
const id = useArtistId()
|
|
50
41
|
const store = useOnchainStore()
|
|
51
|
-
|
|
52
|
-
const ownedByMe = useIsMeCheck(collection.owner)
|
|
53
42
|
</script>
|
|
54
43
|
|
|
55
44
|
<style scoped>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="embed">
|
|
3
|
+
<iframe
|
|
4
|
+
ref="frame"
|
|
5
|
+
frameborder="0"
|
|
6
|
+
:src="src"
|
|
7
|
+
sandbox="allow-scripts"
|
|
8
|
+
></iframe>
|
|
9
|
+
</div>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup>
|
|
13
|
+
defineProps({
|
|
14
|
+
src: String,
|
|
15
|
+
})
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<style scoped>
|
|
19
|
+
.embed {
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 0;
|
|
22
|
+
padding-bottom: 100%;
|
|
23
|
+
position: relative;
|
|
24
|
+
|
|
25
|
+
iframe {
|
|
26
|
+
width: 100%;
|
|
27
|
+
height: 100%;
|
|
28
|
+
position: absolute;
|
|
29
|
+
border: var(--border);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
</style>
|
|
33
|
+
|
package/components/Icon.vue
CHANGED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Actions class="borderless">
|
|
3
|
+
<Button @click="mint">Mint</Button>
|
|
4
|
+
</Actions>
|
|
5
|
+
|
|
6
|
+
<TransactionFlow
|
|
7
|
+
ref="txFlow"
|
|
8
|
+
:text="{
|
|
9
|
+
title: {
|
|
10
|
+
chain: 'Switch Chain',
|
|
11
|
+
requesting: 'Confirm In Wallet',
|
|
12
|
+
waiting: 'Transaction Submitted',
|
|
13
|
+
complete: 'Success!'
|
|
14
|
+
},
|
|
15
|
+
lead: {
|
|
16
|
+
chain: 'Requesting to switch chain...',
|
|
17
|
+
requesting: 'Requesting Signature...',
|
|
18
|
+
waiting: 'Checking mint Transaction...',
|
|
19
|
+
complete: `New token minted...`,
|
|
20
|
+
},
|
|
21
|
+
action: {
|
|
22
|
+
confirm: 'Mint',
|
|
23
|
+
error: 'Retry',
|
|
24
|
+
complete: 'OK',
|
|
25
|
+
},
|
|
26
|
+
}"
|
|
27
|
+
skip-confirmation
|
|
28
|
+
auto-close-success
|
|
29
|
+
@complete="mintCreated"
|
|
30
|
+
/>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script setup>
|
|
34
|
+
const props = defineProps({
|
|
35
|
+
collection: Object,
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const txFlow = ref()
|
|
39
|
+
|
|
40
|
+
const { mint, mintCreated } = useCreateMintFlow(props.collection, txFlow)
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<style scoped>
|
|
44
|
+
menu {
|
|
45
|
+
justify-content: flex-end;
|
|
46
|
+
|
|
47
|
+
@media (--md) {
|
|
48
|
+
grid-column: 2;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
</style>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import Base from './Renderer/Base.client.vue'
|
|
3
|
+
import P5 from './Renderer/P5.client.vue'
|
|
4
|
+
|
|
5
|
+
const components = {
|
|
6
|
+
Base,
|
|
7
|
+
P5,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const props = defineProps(['collection'])
|
|
11
|
+
const { component } = useCreateMintRendererComponent(props.collection)
|
|
12
|
+
</script>
|
|
13
|
+
|
|
14
|
+
<template>
|
|
15
|
+
<div class="mint-detail">
|
|
16
|
+
<MintSelectRenderer :collection="collection" class="borderless" />
|
|
17
|
+
|
|
18
|
+
<MintPreview />
|
|
19
|
+
|
|
20
|
+
<component :is="components[component]" class="card" />
|
|
21
|
+
|
|
22
|
+
<MintAction :collection="collection" />
|
|
23
|
+
</div>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<style>
|
|
27
|
+
.mint-detail {
|
|
28
|
+
display: grid;
|
|
29
|
+
gap: var(--spacer);
|
|
30
|
+
|
|
31
|
+
> *:not(.borderless) {
|
|
32
|
+
border: var(--border);
|
|
33
|
+
padding: var(--spacer);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@media (--md) {
|
|
37
|
+
grid-template-columns: 40% 1fr;
|
|
38
|
+
|
|
39
|
+
.mint-select-renderer {
|
|
40
|
+
grid-column: span 2;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@media (--lg) {
|
|
45
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
</style>
|
|
49
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<article class="mint-preview">
|
|
3
|
+
<div class="static">
|
|
4
|
+
<Image v-if="image" :src="image" alt="Preview" />
|
|
5
|
+
<ImagePreview v-else />
|
|
6
|
+
</div>
|
|
7
|
+
|
|
8
|
+
<Embed v-if="animationUrl" :src="animationUrl" />
|
|
9
|
+
|
|
10
|
+
<h1 :class="{ '': !name }">{{ name || 'Token' }}</h1>
|
|
11
|
+
<p :class="{ '': !description }">
|
|
12
|
+
{{ description || 'No description' }}
|
|
13
|
+
</p>
|
|
14
|
+
</article>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script setup>
|
|
18
|
+
const { image, animationUrl, name, description } = useCreateMintData()
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<style scoped>
|
|
22
|
+
.mint-preview {
|
|
23
|
+
height: 100%;
|
|
24
|
+
place-content: center;
|
|
25
|
+
|
|
26
|
+
svg {
|
|
27
|
+
box-shadow: var(--border-shadow);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.image,
|
|
31
|
+
svg {
|
|
32
|
+
margin-bottom: var(--spacer-sm);
|
|
33
|
+
width: 100%;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.static {
|
|
37
|
+
&:has(+ .embed) {
|
|
38
|
+
width: 30%;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.embed {
|
|
43
|
+
margin: var(--spacer-sm) 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
h1 {
|
|
47
|
+
display: flex;
|
|
48
|
+
gap: var(--spacer-sm);
|
|
49
|
+
align-items: baseline;
|
|
50
|
+
font-size: var(--font-lg);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
p {
|
|
54
|
+
color: var(--muted);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
</style>
|
|
58
|
+
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="mint-renderer-base">
|
|
3
|
+
<Actions>
|
|
4
|
+
<select class="select choose-mode" v-model="mode">
|
|
5
|
+
<option value="file" title="Data URI Encoded File Upload">DATA-URI</option>
|
|
6
|
+
<option value="ipfs" title="Interplanetary File System">IPFS</option>
|
|
7
|
+
<option value="ar" title="Arweave">ARWEAVE</option>
|
|
8
|
+
<option value="http" title="Hypertext Transfer Protocol" disabled>HTTP</option>
|
|
9
|
+
<option value="svg" title="Scalable Vector Graphic" disabled>SVG</option>
|
|
10
|
+
</select>
|
|
11
|
+
</Actions>
|
|
12
|
+
|
|
13
|
+
<div>
|
|
14
|
+
<div v-if="mode === 'file'">
|
|
15
|
+
<FormSelectFile ref="select" @change="setArtifact" />
|
|
16
|
+
<p v-if="! isSmall" class="muted">
|
|
17
|
+
<small>
|
|
18
|
+
Note: This should be a small file, prefferably an SVG like <a href="https://presence.art/tokens/perspective.svg" target="_blank">this one (810 bytes)</a>.
|
|
19
|
+
If it is larger than what we can store within one transaction, the token creation will be split up into multiple transactions.
|
|
20
|
+
</small>
|
|
21
|
+
</p>
|
|
22
|
+
</div>
|
|
23
|
+
<FormInput v-else-if="mode === 'ipfs'" v-model="ipfsCid" placeholder="CID (qmx...)" prefix="ipfs://" required />
|
|
24
|
+
<FormInput v-else-if="mode === 'ar'" v-model="arTxId" placeholder="TX ID (frV...)" prefix="ar://" required />
|
|
25
|
+
|
|
26
|
+
<FormInput v-model="name" placeholder="Title" required />
|
|
27
|
+
<FormInput v-model="description" placeholder="Description" />
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<script setup>
|
|
33
|
+
const props = defineProps({
|
|
34
|
+
decoupleArtifact: {
|
|
35
|
+
type: Boolean,
|
|
36
|
+
default: false,
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
const {
|
|
41
|
+
artifact,
|
|
42
|
+
image,
|
|
43
|
+
name,
|
|
44
|
+
description,
|
|
45
|
+
} = useCreateMintData()
|
|
46
|
+
|
|
47
|
+
const select = ref()
|
|
48
|
+
const mode = ref('file')
|
|
49
|
+
const ipfsCid = ref('')
|
|
50
|
+
const arTxId= ref('')
|
|
51
|
+
|
|
52
|
+
const imageSize = ref(0)
|
|
53
|
+
const isSmall = computed(() => imageSize.value / 1024 < 10)
|
|
54
|
+
const setArtifact = async (file) => {
|
|
55
|
+
try {
|
|
56
|
+
image.value = await imageFileToDataUri(file)
|
|
57
|
+
imageSize.value = file.size
|
|
58
|
+
} catch (e) {
|
|
59
|
+
image.value = ''
|
|
60
|
+
imageSize.value = 0
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
watch(ipfsCid, () => {
|
|
64
|
+
const validated = validateCID(ipfsCid.value)
|
|
65
|
+
if (! validated) {
|
|
66
|
+
image.value = ''
|
|
67
|
+
} else {
|
|
68
|
+
image.value = ipfsToHttpURI(`ipfs://${validated}`)
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
watch(arTxId, () => {
|
|
72
|
+
image.value = `https://arweave.net/${arTxId.value}`
|
|
73
|
+
})
|
|
74
|
+
watch(mode, () => image.value = '')
|
|
75
|
+
|
|
76
|
+
watch(image, () => {
|
|
77
|
+
if (props.decoupleArtifact) return
|
|
78
|
+
|
|
79
|
+
// Copy to image (simple and stupid for the base renderer...)
|
|
80
|
+
artifact.value = image.value
|
|
81
|
+
|
|
82
|
+
// If artifact is empty, reset the select field
|
|
83
|
+
if (! artifact.value) select.value.reset()
|
|
84
|
+
})
|
|
85
|
+
</script>
|
|
86
|
+
|
|
87
|
+
<style scoped>
|
|
88
|
+
.mint-renderer-base {
|
|
89
|
+
display: flex;
|
|
90
|
+
flex-direction: column;
|
|
91
|
+
gap: var(--spacer);
|
|
92
|
+
height: 100%;
|
|
93
|
+
|
|
94
|
+
> div {
|
|
95
|
+
display: flex;
|
|
96
|
+
height: 100%;
|
|
97
|
+
flex-direction: column;
|
|
98
|
+
justify-content: center;
|
|
99
|
+
gap: var(--spacer);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
select.choose-mode {
|
|
104
|
+
width: fit-content;
|
|
105
|
+
}
|
|
106
|
+
</style>
|
|
107
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="mint-renderer-p5">
|
|
3
|
+
|
|
4
|
+
<Tabs initial="base">
|
|
5
|
+
<template #menu="{ active, select }">
|
|
6
|
+
<Button @click="select('base')" :class="{ active: active === 'base' }">Static</Button>
|
|
7
|
+
<Button @click="select('script')" :class="{ active: active === 'script' }">P5 Script</Button>
|
|
8
|
+
</template>
|
|
9
|
+
<template #content="{ active }">
|
|
10
|
+
<MintRendererBase v-show="active === 'base'" decouple-artifact />
|
|
11
|
+
<CodeEditor v-show="active === 'script'" v-model="script" class="full" />
|
|
12
|
+
</template>
|
|
13
|
+
</Tabs>
|
|
14
|
+
</div>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script setup>
|
|
18
|
+
const {
|
|
19
|
+
artifact,
|
|
20
|
+
image,
|
|
21
|
+
animationUrl,
|
|
22
|
+
} = useCreateMintData()
|
|
23
|
+
|
|
24
|
+
const script = ref(DEFAULT_P5_SCRIPT)
|
|
25
|
+
|
|
26
|
+
// Keep the animationURL (for the preview) up to date
|
|
27
|
+
watchEffect(() => {
|
|
28
|
+
animationUrl.value = getP5HtmlUri('Preview', script.value)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Encode the artifact as per how the P5Renderer.sol contract expects it.
|
|
32
|
+
watchEffect(() => {
|
|
33
|
+
artifact.value = encodeAbiParameters(
|
|
34
|
+
[ { type: 'string', name: 'image' }, { type: 'string', name: 'script' } ],
|
|
35
|
+
[ image.value, script.value ],
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
</script>
|
|
39
|
+
|
|
40
|
+
<style>
|
|
41
|
+
.mint-renderer-p5 {
|
|
42
|
+
padding: 0 !important;
|
|
43
|
+
border: 0 !important;
|
|
44
|
+
display: flex;
|
|
45
|
+
flex-direction: column;
|
|
46
|
+
gap: 0;
|
|
47
|
+
|
|
48
|
+
> .tabs {
|
|
49
|
+
height: min-content;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
> .tabs-content {
|
|
53
|
+
border: var(--border);
|
|
54
|
+
border-top: 0;
|
|
55
|
+
height: 100%;
|
|
56
|
+
|
|
57
|
+
> * {
|
|
58
|
+
height: 100%;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
> *:not(.full) {
|
|
62
|
+
padding: var(--spacer);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
67
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<aside class="mint-select-renderer">
|
|
3
|
+
<select
|
|
4
|
+
class="select"
|
|
5
|
+
v-model="selection"
|
|
6
|
+
>
|
|
7
|
+
<option
|
|
8
|
+
v-for="( renderer, index ) in collection.renderers"
|
|
9
|
+
:value="index"
|
|
10
|
+
:title="renderer.name"
|
|
11
|
+
>{{ renderer.name }}</option>
|
|
12
|
+
<option disabled>----</option>
|
|
13
|
+
<option value="new">Install New</option>
|
|
14
|
+
</select>
|
|
15
|
+
</aside>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script setup>
|
|
19
|
+
const { collection } = defineProps(['collection'])
|
|
20
|
+
const id = useArtistId()
|
|
21
|
+
|
|
22
|
+
const store = useOnchainStore()
|
|
23
|
+
onMounted(() => store.fetchCollectionRenderers(collection.address))
|
|
24
|
+
|
|
25
|
+
const { renderer, reset } = useCreateMintData()
|
|
26
|
+
const selection = ref(renderer.value)
|
|
27
|
+
watch(selection, () => {
|
|
28
|
+
if (selection.value === 'new') {
|
|
29
|
+
return navigateTo({ name: 'id-collection-renderers', params: { id: id.value, collection: collection.address } })
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
renderer.value = selection.value
|
|
33
|
+
|
|
34
|
+
reset()
|
|
35
|
+
})
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<style scoped>
|
|
39
|
+
.mint-select-renderer {
|
|
40
|
+
display: grid;
|
|
41
|
+
gap: var(--spacer);
|
|
42
|
+
|
|
43
|
+
@media (--md) {
|
|
44
|
+
display: flex;
|
|
45
|
+
justify-content: space-between;
|
|
46
|
+
|
|
47
|
+
.select {
|
|
48
|
+
width: fit-content;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Button @click="install">Install</Button>
|
|
3
|
+
<TransactionFlow
|
|
4
|
+
ref="txFlow"
|
|
5
|
+
:request="installRequest"
|
|
6
|
+
:text="{
|
|
7
|
+
title: {
|
|
8
|
+
chain: 'Switch Chain',
|
|
9
|
+
requesting: 'Confirm In Wallet',
|
|
10
|
+
waiting: 'Transaction Submitted',
|
|
11
|
+
complete: 'Success!'
|
|
12
|
+
},
|
|
13
|
+
lead: {
|
|
14
|
+
chain: 'Requesting to switch chain...',
|
|
15
|
+
requesting: 'Requesting Signature...',
|
|
16
|
+
waiting: 'Checking Transaction...',
|
|
17
|
+
complete: `New Renderer registered...`,
|
|
18
|
+
},
|
|
19
|
+
action: {
|
|
20
|
+
confirm: 'Register Renderer',
|
|
21
|
+
error: 'Retry',
|
|
22
|
+
complete: 'OK',
|
|
23
|
+
},
|
|
24
|
+
}"
|
|
25
|
+
skip-confirmation
|
|
26
|
+
auto-close-success
|
|
27
|
+
/>
|
|
28
|
+
</template>
|
|
29
|
+
|
|
30
|
+
<script setup>
|
|
31
|
+
const { $wagmi } = useNuxtApp()
|
|
32
|
+
const { collection, renderer } = defineProps(['collection', 'renderer'])
|
|
33
|
+
const store = useOnchainStore()
|
|
34
|
+
const chainId = useMainChainId()
|
|
35
|
+
|
|
36
|
+
const installRequest = computed(() => async () => {
|
|
37
|
+
return writeContract($wagmi, {
|
|
38
|
+
abi: MINT_ABI,
|
|
39
|
+
chainId,
|
|
40
|
+
address: collection.address,
|
|
41
|
+
functionName: 'registerRenderer',
|
|
42
|
+
args: [
|
|
43
|
+
renderer.address,
|
|
44
|
+
],
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
const txFlow = ref()
|
|
48
|
+
const installing = ref(false)
|
|
49
|
+
const install = async () => {
|
|
50
|
+
installing.value = true
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
await txFlow.value.initializeRequest(installRequest.value)
|
|
54
|
+
|
|
55
|
+
await store.fetchCollectionRenderers(collection.address)
|
|
56
|
+
} catch (e) {
|
|
57
|
+
console.error(e)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
installing.value = false
|
|
61
|
+
}
|
|
62
|
+
</script>
|