Alephium's UX
Building for all humans.
The challenge of hiding the tech away to make innovation accessible to all.
Mikaël Vaivre @mika_pote
July 2023
const { data: unknownAssetsBalances } = useQueriesData(
unknownAssetsIds.map((id) => ({
...queries.assets.balances.addressToken(addressHash, id),
enabled: unknownAssetsIds.length > 0
}))
)
let tokensWithBalanceAndMetadata = flatMap(tokenBalances, (t) => {
const metadata = find(fungibleTokens, { id: t.id })
return metadata ? [{ ...t, ...metadata, balance: BigInt(t.balance), lockedBalance: BigInt(t.lockedBalance) }] : []
})
tokensWithBalanceAndMetadata = sortBy(tokensWithBalanceAndMetadata, [
(t) => !t.verified,
(t) => !t.name,
(t) => t.name.toLowerCase(),
'id'
])
Alephium's UX
Building for all humans.
The challenge of hiding the tech away to make innovation accessible to all.
Mikaël Vaivre @mika_pote
July 2023
const { data: unknownAssetsBalances } = useQueriesData(
unknownAssetsIds.map((id) => ({
...queries.assets.balances.addressToken(addressHash, id),
enabled: unknownAssetsIds.length > 0
}))
)
let tokensWithBalanceAndMetadata = flatMap(tokenBalances, (t) => {
const metadata = find(fungibleTokens, { id: t.id })
return metadata ? [{ ...t, ...metadata, balance: BigInt(t.balance), lockedBalance: BigInt(t.lockedBalance) }] : []
})
tokensWithBalanceAndMetadata = sortBy(tokensWithBalanceAndMetadata, [
(t) => !t.verified,
(t) => !t.name,
(t) => t.name.toLowerCase(),
'id'
])
First principles
const { data: unknownAssetsBalances } = useQueriesData(
unknownAssetsIds.map((id) => ({
...queries.assets.balances.addressToken(addressHash, id),
enabled: unknownAssetsIds.length > 0
}))
)
let tokensWithBalanceAndMetadata = flatMap(tokenBalances, (t) => {
const metadata = find(fungibleTokens, { id: t.id })
return metadata ? [{ ...t, ...metadata, balance: BigInt(t.balance), lockedBalance: BigInt(t.lockedBalance) }] : []
})
tokensWithBalanceAndMetadata = sortBy(tokensWithBalanceAndMetadata, [
(t) => !t.verified,
(t) => !t.name,
(t) => t.name.toLowerCase(),
'id'
])
(my)
First principles
const { data: unknownAssetsBalances } = useQueriesData(
unknownAssetsIds.map((id) => ({
...queries.assets.balances.addressToken(addressHash, id),
enabled: unknownAssetsIds.length > 0
}))
)
let tokensWithBalanceAndMetadata = flatMap(tokenBalances, (t) => {
const metadata = find(fungibleTokens, { id: t.id })
return metadata ? [{ ...t, ...metadata, balance: BigInt(t.balance), lockedBalance: BigInt(t.lockedBalance) }] : []
})
tokensWithBalanceAndMetadata = sortBy(tokensWithBalanceAndMetadata, [
(t) => !t.verified,
(t) => !t.name,
(t) => t.name.toLowerCase(),
'id'
])
(my)
First principles
const { data: unknownAssetsBalances } = useQueriesData(
unknownAssetsIds.map((id) => ({
...queries.assets.balances.addressToken(addressHash, id),
enabled: unknownAssetsIds.length > 0
}))
)
let tokensWithBalanceAndMetadata = flatMap(tokenBalances, (t) => {
const metadata = find(fungibleTokens, { id: t.id })
return metadata ? [{ ...t, ...metadata, balance: BigInt(t.balance), lockedBalance: BigInt(t.lockedBalance) }] : []
})
tokensWithBalanceAndMetadata = sortBy(tokensWithBalanceAndMetadata, [
(t) => !t.verified,
(t) => !t.name,
(t) => t.name.toLowerCase(),
'id'
])
(my)
ITERATE
(a lot)
First principles
const { data: unknownAssetsBalances } = useQueriesData(
unknownAssetsIds.map((id) => ({
...queries.assets.balances.addressToken(addressHash, id),
enabled: unknownAssetsIds.length > 0
}))
)
let tokensWithBalanceAndMetadata = flatMap(tokenBalances, (t) => {
const metadata = find(fungibleTokens, { id: t.id })
return metadata ? [{ ...t, ...metadata, balance: BigInt(t.balance), lockedBalance: BigInt(t.lockedBalance) }] : []
})
tokensWithBalanceAndMetadata = sortBy(tokensWithBalanceAndMetadata, [
(t) => !t.verified,
(t) => !t.name,
(t) => t.name.toLowerCase(),
'id'
])
(my)
DON'T BE SCARED TO TRY
(live)
ITERATE
(a lot)
First principles
const { data: unknownAssetsBalances } = useQueriesData(
unknownAssetsIds.map((id) => ({
...queries.assets.balances.addressToken(addressHash, id),
enabled: unknownAssetsIds.length > 0
}))
)
let tokensWithBalanceAndMetadata = flatMap(tokenBalances, (t) => {
const metadata = find(fungibleTokens, { id: t.id })
return metadata ? [{ ...t, ...metadata, balance: BigInt(t.balance), lockedBalance: BigInt(t.lockedBalance) }] : []
})
tokensWithBalanceAndMetadata = sortBy(tokensWithBalanceAndMetadata, [
(t) => !t.verified,
(t) => !t.name,
(t) => t.name.toLowerCase(),
'id'
])
(my)
ITERATE
SIMPLE IS BEAUTIFUL
(but simple is hard)
DON'T BE SCARED TO TRY
(live)
(a lot)
First principles
const { data: unknownAssetsBalances } = useQueriesData(
unknownAssetsIds.map((id) => ({
...queries.assets.balances.addressToken(addressHash, id),
enabled: unknownAssetsIds.length > 0
}))
)
let tokensWithBalanceAndMetadata = flatMap(tokenBalances, (t) => {
const metadata = find(fungibleTokens, { id: t.id })
return metadata ? [{ ...t, ...metadata, balance: BigInt(t.balance), lockedBalance: BigInt(t.lockedBalance) }] : []
})
tokensWithBalanceAndMetadata = sortBy(tokensWithBalanceAndMetadata, [
(t) => !t.verified,
(t) => !t.name,
(t) => t.name.toLowerCase(),
'id'
])
(my)
ITERATE
SIMPLE IS BEAUTIFUL
(but simple is hard)
DON'T BE SCARED TO TRY
(live)
(a lot)
(especially for engineers)
First principles
const { data: unknownAssetsBalances } = useQueriesData(
unknownAssetsIds.map((id) => ({
...queries.assets.balances.addressToken(addressHash, id),
enabled: unknownAssetsIds.length > 0
}))
)
let tokensWithBalanceAndMetadata = flatMap(tokenBalances, (t) => {
const metadata = find(fungibleTokens, { id: t.id })
return metadata ? [{ ...t, ...metadata, balance: BigInt(t.balance), lockedBalance: BigInt(t.lockedBalance) }] : []
})
tokensWithBalanceAndMetadata = sortBy(tokensWithBalanceAndMetadata, [
(t) => !t.verified,
(t) => !t.name,
(t) => t.name.toLowerCase(),
'id'
])
(my)
ITERATE
DON'T BE SCARED TO TRY
DON'T REINVENT THE WHEEL
(but sometimes do)
SIMPLE IS BEAUTIFUL
(but simple is hard)
(live)
(a lot)
(especially for engineers)
First principles
const { data: unknownAssetsBalances } = useQueriesData(
unknownAssetsIds.map((id) => ({
...queries.assets.balances.addressToken(addressHash, id),
enabled: unknownAssetsIds.length > 0
}))
)
let tokensWithBalanceAndMetadata = flatMap(tokenBalances, (t) => {
const metadata = find(fungibleTokens, { id: t.id })
return metadata ? [{ ...t, ...metadata, balance: BigInt(t.balance), lockedBalance: BigInt(t.lockedBalance) }] : []
})
tokensWithBalanceAndMetadata = sortBy(tokensWithBalanceAndMetadata, [
(t) => !t.verified,
(t) => !t.name,
(t) => t.name.toLowerCase(),
'id'
])
(my)
DON'T REINVENT THE WHEEL
(but sometimes do)
ITERATE
(a lot)
DON'T BE SCARED TO TRY
(live)
SIMPLE IS BEAUTIFUL
(but simple is hard)
(especially for engineers)
Alephium when I joined in 2019
ITERATE
(a lot)
Principle #1
Good design takes time.
ITERATE
(a lot)
Principle #1
ITERATE
ADAPT
EVOLVE
Alephium
In 2023
Back in 2017 I thought that the industry was getting mature. That the bull run would finally bring blockchain to the masses.
I thought that 2009 to 2017 was enough time to iterate.
IN UI & UX?
ITERATE
We're still young.
I was wrong.
IN UI & UX?
UX needs time to mature.
ITERATE
(often more than tech)
IN UI & UX?
ITERATE
We're still young.
I was wrong.
UX needs time to mature.
Alephium is trying to push the industry forward, leading by example.
Alephium
ITERATE @
We're still young.
I was wrong.
UX needs time to mature.
Alephium is trying to push the industry forward, leading by example.
Alephium
ITERATE @
DON'T REINVENT THE WHEEL
(but sometimes do)
ITERATE
(a lot)
DON'T BE SCARED TO TRY
(live)
SIMPLE IS BEAUTIFUL
(but simple is hard)
(especially for engineers)
First principles
(my)
If it's not good, fail fast and iterate.
You won't know it's good until your users tell you it's good.
DON'T BE SCARED TO TRY
(live)
Principle #2
If it's not good, fail fast and iterate.
You don't know it's good until your users tell you it's good.
DON'T BE SCARED TO TRY
(live)
Principle #2
DON'T REINVENT THE WHEEL
(but sometimes do)
ITERATE
(a lot)
DON'T BE SCARED TO TRY
(live)
SIMPLE IS BEAUTIFUL
(but simple is hard)
(especially for engineers)
First principles
(my)
SIMPLE IS BEAUTIFUL
(but simple is hard)
(especially for engineers)
How do you design an efficient, easy-to-trust and easy to use tool...
...without sprinkling useless noise all over your designs?
...without appearing too gimmicky or too gamified...
...without being cold and boring...
Principle #3
SIMPLE IS BEAUTIFUL
(but simple is hard)
(especially for engineers)
How do you abstract the complexity of the code you know by heart...
...while leveraging the full potential of what you've built.
How do you design an efficient, easy-to-trust and easy to use tool...
...by sprinkling useless noise all over your designs?
...without appearing too gimmicky or too gamified...
...without being cold and boring...
Principle #3
SIMPLE IS BEAUTIFUL
Hide complexity by default
Principle #3
SIMPLE IS BEAUTIFUL
Add fun little details
SIMPLE IS BEAUTIFUL
Focus on current action
SIMPLE IS BEAUTIFUL
Focus on current action
DON'T REINVENT THE WHEEL
(but sometimes do)
ITERATE
(a lot)
DON'T BE SCARED TO TRY
(live)
SIMPLE IS BEAUTIFUL
(but simple is hard)
(especially for engineers)
First principles
(my)
DON'T REINVENT THE WHEEL
(but sometimes do)
- Get inspired by the best.
- Always compare your products with the mainstream (widely adopted) products. Don't build blindly.
- It's not because we're not big that we can't do big things.
And sometimes you're convinced that you can do better than most. If the risk isn't huge, just try. You may just be right! If not... fail and iterate.
Principle #4
DON'T REINVENT THE WHEEL
(but sometimes do)
Extension frustrations
Principle #4
Thank you
Thank you
I'm looking forward to building more great things for you.
Alephium UX
By Mikael Vaivre
Alephium UX
- 5,192