diff --git a/punks.auction/.env.example b/punks.auction/.env.example
index 1e5c987f..1421a93e 100644
--- a/punks.auction/.env.example
+++ b/punks.auction/.env.example
@@ -10,3 +10,9 @@ NUXT_PUBLIC_EVM_WALLET_CONNECT_PROJECT_ID=
# Public indexer base URL (Ponder/Postgres GraphQL endpoint). Defaults to the
# shared production indexer in nuxt.config.ts; override per environment.
NUXT_PUBLIC_INDEXER_URL=https://indexer.punksmarket.app
+
+# Broker brand shown in the "branded" Contact-broker preview. Defaults to
+# "Canon" in nuxt.config.ts. NUXT_PUBLIC_BROKER_LOGO is inline SVG markup —
+# use fill="currentColor" so it inherits the surrounding text color.
+NUXT_PUBLIC_BROKER_NAME=Canon
+NUXT_PUBLIC_BROKER_LOGO=
diff --git a/punks.auction/app/components/Punk/Detail/Market.vue b/punks.auction/app/components/Punk/Detail/Market.vue
index f47c75b4..4d37c27a 100644
--- a/punks.auction/app/components/Punk/Detail/Market.vue
+++ b/punks.auction/app/components/Punk/Detail/Market.vue
@@ -15,6 +15,35 @@
class="market-panel"
>
+
+
Top bid
+
+
+ by
+
+
+
+
+
+ None
+
+
+
+
+
+
+
Listing
@@ -32,23 +61,17 @@
>
Not for sale
-
-
-
Top bid
-
-
- by
-
-
-
-
-
- None
-
+ Wallet last active {{ ownerLastActiveAgo }}
+
+
+
+
+
@@ -123,20 +146,12 @@
.
-
-
-
-
+
@@ -228,6 +243,26 @@ const canBuy = computed(() => {
)
})
+// Owner's wallet last-active, sourced from the indexer's tx-from tracking, so a
+// broker can gauge how reachable the holder is. Custody set covers vault/stash;
+// the EOA drives the last-active lookup.
+const ownerAddresses = computed(() => {
+ const set = new Set()
+ if (resolvedOwner.value) set.add(resolvedOwner.value)
+ if (nativeOwner.value) set.add(nativeOwner.value)
+ return [...set]
+})
+const { stats: ownerStats } = useAccountStats({
+ addresses: ownerAddresses,
+ eoa: () => resolvedOwner.value ?? undefined,
+})
+const ownerLastActiveIso = computed(() =>
+ ownerStats.value.lastActiveAt
+ ? new Date(ownerStats.value.lastActiveAt * 1000).toISOString()
+ : undefined,
+)
+const ownerLastActiveAgo = useTimeAgo(ownerLastActiveIso)
+
let refreshToken = 0
async function refresh() {
@@ -386,6 +421,16 @@ function sameAddress(a?: Address | string | null, b?: Address | string | null) {
border: 0;
}
+.last-active {
+ margin: var(--size-1) 0 0;
+ font-size: var(--font-xs);
+ color: var(--text-dim);
+}
+
+.cell-action {
+ margin-top: var(--size-4);
+}
+
.label {
margin-bottom: var(--size-1);
color: var(--text-dim);
@@ -404,8 +449,6 @@ function sameAddress(a?: Address | string | null, b?: Address | string | null) {
align-items: center;
gap: var(--size-2);
flex-wrap: wrap;
- padding-top: var(--size-3);
- border-top: var(--border);
}
.action-group {
diff --git a/punks.auction/app/components/Punk/Detail/Market/BrokerContact.vue b/punks.auction/app/components/Punk/Detail/Market/BrokerContact.vue
new file mode 100644
index 00000000..aa58100b
--- /dev/null
+++ b/punks.auction/app/components/Punk/Detail/Market/BrokerContact.vue
@@ -0,0 +1,282 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/punks.auction/app/components/Punk/Detail/Market/BrokerLogo.vue b/punks.auction/app/components/Punk/Detail/Market/BrokerLogo.vue
new file mode 100644
index 00000000..e39ff0e8
--- /dev/null
+++ b/punks.auction/app/components/Punk/Detail/Market/BrokerLogo.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
diff --git a/punks.auction/nuxt.config.ts b/punks.auction/nuxt.config.ts
index 087902ab..d94ace1d 100644
--- a/punks.auction/nuxt.config.ts
+++ b/punks.auction/nuxt.config.ts
@@ -66,6 +66,14 @@ export default defineNuxtConfig({
// shared indexer that backs both punksmarket.app and this app.
// Override with NUXT_PUBLIC_INDEXER_URL.
indexerUrl: 'https://indexer.punksmarket.app',
+ // Broker brand shown in the "branded" Contact-broker preview. Override
+ // per deployment with NUXT_PUBLIC_BROKER_NAME / NUXT_PUBLIC_BROKER_LOGO.
+ // `logo` is inline SVG markup; use `fill="currentColor"` so it inherits
+ // the surrounding text color.
+ broker: {
+ name: 'Canon',
+ logo: '',
+ },
evm: {
walletConnectProjectId: '',
chains: {