district0x / name-bazaar Goto Github PK
View Code? Open in Web Editor NEWA peer-to-peer marketplace for the exchange of names registered via the Ethereum Name Service
License: Eclipse Public License 1.0
A peer-to-peer marketplace for the exchange of names registered via the Ethereum Name Service
License: Eclipse Public License 1.0
Implement comprehensive logging of all actions happening on node.js server.
Events types that should be logged:
Tests must be extra comprehensive as contracts deal with money and name ownerships.
Tests should be added here: https://github.com/district0x/name-bazaar/blob/master/test/name_bazaar/smart_contract_tests.cljs
Following things should be tested: (if you think I forgot sth, feel free to add).
You can reorder testings of those things as it makes most sense codewise.
extensionDuration
Users should get email notification when:
struct Requests {
string name;
uint latestIndex; // Increments every time new offering is created
mapping(uint => address[]) requesters;
mapping(uint => mapping(address => bool)) hasRequested;
}
Explore possibility to move from Semantic Grid into CSS Grid. If this proves to be feasible on NB, we'll use that for all other districts. The end goal is to separate components code from visual layouting as much as possible. That means, moving layouting into CSS.
I'm not sure how smooth can migration be, but would be great if it can be applied continuously without breaking current layout. So, if you migrate some components, commit it, we'll take a look and test in different browsers and if all good, you'll continue. NameBazaar should look exactly same after migration.
There seems to be multiple ways of doing CSS Grid, like via grid-template-areas or grid-template-rows, etc. I don't know I'm no expert, so play around it and find best way ;)
Edit: We'll still keep other Semantic components unrelated to layouting as they are
I have one domain listed for both auction and buynow, how do I delete one ?
Actually one of them has ownership issues as the transfer was done via the other one. Is this why the domain is not listed in the search area ?
Implement changes related to following point from audit: https://gist.github.com/Arachnid/3416e5a85b5b67eb9cdfa2252a5e28d9#unnecessary-complication-due-to-transferprice-parameter-to-auctionofferingfinalize
We can remove transferPrice parameter and instead make fallback automatic. To do so, we'll use Solidity's send
function instead of transfer
.
send
function doesn't throw error if transacting fails, but returns false.
So instead of this
if (transferPrice) {
offering.originalOwner.transfer(offering.price);
} else {
self.pendingReturns[offering.originalOwner] =
self.pendingReturns[offering.originalOwner].add(offering.price);
We'll write this:
if (!offering.originalOwner.send(offering.price)) {
self.pendingReturns[offering.originalOwner] =
self.pendingReturns[offering.originalOwner].add(offering.price);
}
In similar fashion we can edit bid function, where funds will be tried to sent to overbid user instantly and only after that fails, we'll put it into pending returns. Tests will need to be edited, that instead of pending returns it checks user's balance if overbid amount was returned.
Testing fallback pending returns scenario would be pretty tricky, it would require creating contract with fallback function that always fails and bid through this contract. I'd leave implementations of this after release, as we have more important tasks to do first.
It would be great to be able to sign in using the Ledger Nano S as I can't connect addresses to Meta Mask etc.
db_sync.cljs should be able to recover if underlying blockchain node is restarted/disconnected and got online again.
All listeners should be stopped once we get first connection error, so we don't get flooded with additional errors. Then there should be interval checking every second if we got online again and setup syncing listeners again.
In-memory db should be wiped out and start syncing all over again, because we don't know what data was added meanwhile Ethereum node was offline.
Right now we have pages like:
https://namebazaar.io/user/0x24ac2648175b1b9a3564ad6a3680569dfbb896b7/offerings
https://namebazaar.io/user/0x24ac2648175b1b9a3564ad6a3680569dfbb896b7/bids
https://namebazaar.io/user/0x24ac2648175b1b9a3564ad6a3680569dfbb896b7/purchases
Goal is to be able to use URLs like:
https://namebazaar.io/user/johndoe/offerings
https://namebazaar.io/user/johndoe/bids
https://namebazaar.io/user/johndoe/purchases
Where johndoe
would represent address resolved from ENS name johndoe.eth
.
So when application detects that in URL is not an address (cljs-web3.core/address?
is false), it'll try to perform ENS lookup.
Steps you'll need to to do to be able to do lookup:
ens/PublicResolver.sol
contract to compile-solidity.sh
:public-resolver
entry with zero address into name-bazaar.shared.smart-contracts
, so UI loads ABI at app start up.:ens.records/load
).addr
to try to load associated Ethereum address. If it's valid non-zero address, then continues loading page as normal. If it's not valid address it displays same error as in step 4.The app should automatically detect address change in MetaMask. There's likely no listener, probably just by querying get-accounts in interval. Saw it functioning here: https://faucet.metamask.io/
New Manage Name Page should look like this:
:active-address
, but allows different address for inputweb3/address?
0x5ffc014343cd971b7eb70732021e26c35b744cc4
valid-ens-name?
:active-address
0x5ffc014343cd971b7eb70732021e26c35b744cc4
valid-ens-name?
web3/address?
Truffle relased Ganache, a powerfull testrpc replacement: http://truffleframework.com/ganache/
We could investigate how attainable it is to replace testrpc with Ganache in our dev environment, ideally as a part of the docker build.
Add sharing functionality into Facebook and Twitter buttons on My Offerings and offering detail pages. Beware, when user wants to share My Offerings page, it actually should share his user offerings page: /user/<useraddress>/offerings
., not /my-offerings
Adding "Delete" button for offerers to remove offering.
Steps to implement:
/**
* @dev Modifier to make a function callable only when offering contract doesn't have name ownership
*/
modifier onlyWhenContractIsNotNodeOwner() {
require(!isContractNodeOwner());
_;
}
/**
* @dev Unregisters offering for not displaying it in UI
* Cannot be run if contract has ownership or it was already transferred to new owner
*/
function unregister()
public
onlyOriginalOwner
onlyWithoutNewOwner
onlyWhenContractIsNotNodeOwner
{
// New owner is not really this address, but it's the way to recogize if offering
// was unregistered without having separate var for it, which is costly
offering.newOwner = 0xdeaddead;
fireOnChanged("unregister");
}
name-bazaar.server.db/search-offerings
to not return offerings with :new-owner
of 0xdeaddead
, similarly as there's handling of emergency-state-new-owner
.:offering/unregistered?
into name-bazaar.shared.utils/parse-offering
and do detection there.This is all very straightforward, but life ain't that nice and easy. We need to support deletion for already existing offerings. I recommend following hack:
When you detect offering version is 1
or 100000
(can add prop :offering/supports-unregister?
),
use methods :buy-now-offering/set-settings
and :auction-offering/set-settings
to set some very unlikely price. e.g 23423982302342 (in wei) and that way you'll simulate deletion. Rest is pretty much the same pattern. On surface user should not be able to tell difference.
Debounced fields should be:
at #/offerings:
at #/offering-requests
Currently it's disabled for winning bidder to bid again. This might be needed if user wants to raise bid and leave away from computer.
For this issue, make changes only in smart contract: AuctionOfferingLibrary.sol. And also add some simple test for this: When user overbids himself, highest bid is correctly added up and user has no pending returns.
You don't need to make changes in UI for this issue.
Users can create offerings outside namebazaar UI and therefore go around UTS46 normalisation and create offering for what we would consider invalid name.
Into name-bazaar.shared.utils/parse-offering
add 2 more props:
:offering/valid-name?
, which has result of name-bazaar.ui.utils/valid-ens-name?
:offering/normalized?
, which is true if name stays exactly same as when run through normalize function. In browser it's js/EthEnsNamehash.normalize
in node.js (aget (js/require "eth-ens-namehash") "normalize")
. (Must detect environment to choose correct one)In db_sync.cljs
on on-offering-added event, we simply skip adding into in-memory db offerings that have either :offering/valid-name?
false or :offering/normalized?
false.
That way we get it out of search results, but such offering will be still accessible on offering detail page in UI.
In UI we add warning, same way as below and disable buy/bid button in both cases.
Warning text for both cases:
WARNING: Offered name is not compatible with UTS46 normalisation, therefore buying or bidding is disabled.
Here are files for email template: Email Template.zip.
Ask me for Sendgrid credentials on chat. You should create a template there. You'll see Ethlance template there already. See how substitutions are done there. Substitutions are placeholders that get replaced programatically when sending email. In ethlance-emailer it's done like this. So you should have 4 substitutions here: Header title, Body text, Button text, Button href.
Make NB work in toshi. From what I read, you need to create chat bot and then give it WebView action. WebView should have injected web3 automatically, so everything "should" just work.
Please create repo for chat bot under district0x organisation as name-bazaar-toshi
.
Chatbot should work basically the same way as Cryptokitties one. It should display one menu with links and one button to visit page.
UI should be already mobile friendly, but Transaction Log opener is currently hidden for mobile screens. You'll need to enable it following way: (only CSS)
This is preparation issue for name registration issue.
Currently we have at ens/HashRegistrarSimplified.sol
modified version of original HashRegistrarSimplified.sol. Modified in a way that it supports instant registration for development purposes of our project. The problem is, I modified it in too impactful way, that it no longer can serve as original registrar, only instant registrar.
Your task is to take again original registrar code and add function register
for instant registration, but don't modify other functions of contract, so it still can be used in original way, which we'll need for development of name registration.
Function state
doesn't need to return correct state for instantly registered names, because that would complicate things too much.
Here's example of current register
code:
function register(bytes32 _hash) {
startAuction(_hash);
var sealedBid = shaBid(_hash, msg.sender, msg.value, 0);
newBid(sealedBid);
unsealBid(_hash, msg.value, 0);
finalizeAuction(_hash);
}
The problem is that function calls all these high level functions, which have modified internals of them. What you need is to put internals into register
function (without unwanted conditions) and high level functions like startAuction
, newBid
, etc. leave untouched.
Hello,
What are some names that are actually used?
Where else can these names be bought?
Those side effects should be done in reg-fx
and called as regular re-frame events.
name-bazaar/src/name_bazaar/ui/core.cljs
Lines 40 to 43 in bb040c7
The problem is that (history/start! constants/routes)
fires [:active-page-changed]
even before app is bootstrap, therefore before :district0x/smart-contracts-loaded
. This causes error, because :active-page-changed
assumes :district0x/smart-contracts-loaded
.
Currently I used little hack to avoid error:
name-bazaar/src/name_bazaar/ui/events.cljs
Lines 145 to 146 in bb040c7
name-bazaar/src/name_bazaar/ui/core.cljs
Line 50 in bb040c7
For (.-onhashchange js/window)
we already have district0x.ui.window-fx
file, you can put new reg-fx
there.
For (history/start! constants/routes)
you can create district0x.ui.history-fx
. Don't put into district0x.ui.history
because this file is required many times, so reg-fx
is not overwritten every time.
When server is not synced yet, but requests are coming to server it spits following error:
{:level :error, :message "Unexpected error occured", :meta {:raw-error #object[TypeError TypeError: Cannot read property 'get' of null], :error {}, :ns "name-bazaar.server.api", :line 23, :file "/home/ubuntu/name-bazaar/src/name_bazaar/server/api.cljs"}, :?file "/tmp/form-init1063880031196546695.clj", :?line nil, :timestamp #inst "2017-10-30T01:43:49.871-00:00"}
It should return 503 Service Unavailable
error.
Have suspicion that this somehow interferes with syncing itself, but not confirmed.
I would like to know or be able to see how many views my offering(s) have received.
Implement page for ENS name registration.
These 2 issues must be done, before this issue: #102 and #92
Here are designed screens with different states of registration:
As user types into text field, app checks state of the name. (:registrar.entries/load
)
When name is available we display screen as below on the screen.
Put Lorem Ipsum meanwhile there, there will go some instructions
"Bid Now" button calls startAuctionsAndBid
of Registrar
"Open Without Bids" calls startAuction
For "Add to Calendar" use react-add-to-calendar
Button is disabled until reveal phase happens
Disabled button doesn't need to look like on designs, just pass it :disabled true
I don't have screen for this state, but it's basically same as previous screen, with text under input from first screen ("The name is available for bids") and form is also like first screen except "Open without bid" button is not there.
If there's no highest bidder yet, write "none".
Winning bidder link should go to user offerings page
Basically same as previous screen. "Finalize" button is disabled until end of reveal phase.
Create offering button goes to create offering page with pre-filled offering name
For Name Information and Registrar Information reuse component we already have from name detail page. Design does not reflect exactly what we have currently in app, ignore that.
Time to renewal is 2 years from the end of the auction.
As you can see, on each screen there are 2/3 of these buttons. When user makes bid, he must seal it, so others can't see how much he has bid. You seal bid in following way: sha3(ENS node, User Address, Value of Bid, Salt). Where Salt is hashed password user should choose. See Registrar smart-contract for more details, or Google. We'll generate Salt string for users, from random 10 char string (district0x.shared.utils/rand-str
). Then we'll be storing those hashed salts in localstorage, so users can later reveal bids. For hashing Salt use name-bazaar.ui.utils/sha3
So:
When user sends bid transaction or just opens auction, we save bid into :registration-bids
in db (which will be synced with localstorage).
When user clicks "Backup bids", it exports contents of :registration-bids
as JSON and exports it to browser. Similarly as https://registrar.ens.domains/ does it.
"Import Bids" will do other way around. Read JSON file and import bids to :registration-bids
and localstorage. If imported file is invalid, snackbar informs user.
At certain states, "Remove name" is available. It is to remove current name from :registration-bids
. This button is displayed only if user actually has current name in :registration-bids
.
Format of :registration-bids
as well as exported JSON file is:
{user-address {node {:name "somename.eth" :salt "0x12345..."}}}
So, when user opens registration page, app loads current state of all his :registration-bids
for current :active-address
. (:registrar.entries/load
)
Make sure you don't just load phase from Registrar smart-contract, but calculate it client-side and compare to :now
, as we want to have phase changed in UI automatically while user is on the page.
Under the text field it always shows the most important information about his :registration-bids
state. These are all possible texts there, ordered by importance (It always shows only 1 line at the time, the most important one):
When user clicks on text field, it gives him autocomplete suggestions of :registration-bids
for current :active-address
.
Each row also displays current state of a bid. This are all possible states, in order they should be displayed in suggested list (by importance):
To be able to effectively test all different states, you'll need to be fast-forwarding time in TestRPC (cljs-web3.evm/increase-time!
) as well as fast-forwarding :now
in re-frame db. Or you can modify phase durations in HashRegistrarSimplified.sol
. You can try both approaches.
I already added all icons you'll need, here are classes:
.arrow-up
Winning during reveal phase
.hammer-remove
Remove Name
.hammer-arrow-left
Import Bids
.hammer-arrow-right-left
Backup Bids
.flag2
Waiting for finalization
.dots
Waiting for reveal phase
.hammer2
User made bid, waiting for reveal phase
.loading
Loading
.user2
Name is owned
.check
Finalized
.clock2
Bid is waiting to be revealed
.times
Outbid
Please commit continuously so I can review
Happy hacking!
URL like https://namebazaar.io/offerings/create?name=bitcoin
should prefill name input for creating offering and trigger ownership check.
On ENS name detail. e.g https://namebazaar.io/name/buterinvitalik.eth, or when expanded offering request: If :active-address
is :ens.record/owner
there should be new link displayed below "Open in Etherscan" and "Add to watched names" -> "Create offering", that will go to create offering page and prefill name input.
This feature will come in handy for prepared Registration feature, so this should be ready before implementing Registration.
I think this needs to be fixed, because right now people think you can have ENS names like one.eth, dog.eth, wall.eth... I think this needs to be addressed at least in requested names. Here's pictures for references:
https://i.imgur.com/15DjRDN.png (namebazaar request page)
https://i.imgur.com/kVh0ZLp.png (only domains with 7+ char count can be created)
I suggest that words with less than 7 characters shouldn't be seeable.
https://i.imgur.com/np9Igw3.png (In this case clicking enter should pop an error message saying the char count is less than 7)
If I remember correctly, the char count limitation will be decreased to 4 chars in the future, but there's still a lot time before that. Therefore, NameBazaar is misleading in this sense, so I feel this should be addressed in the following commits and fixed.
I just realized I hold all my ENS domains on my trezor wallets. Trezor users can't use metamask and even if we could export our keys, we would rather not. Namebazaar needs to be supporting hardware wallets too.
I guess explicitly supporting Trezor isn't necessary as far as you provide us with the contract addresses and ABI's to interact with contracts without the website.
Try out if https://www.prerender.cloud/ is viable solution for our server side rendering. You can be testing it on https://beta.namebazaar.io.
Site must be crawlable and be served with page specific tags. Not sure how does this work in prerender, but since meta tags are out of reach of React. Maybe we can edit app the way that react renders meta tags also. Or use vanilla JS.
Use nginx implementation of https://www.prerender.cloud/
Right now we're using urls like: https://namebazaar.io/#/offerings
, we need to change that into urls like https://namebazaar.io/offerings
using pushy library. This is needed as a preparation for Open Graph implementation, which will be done later. Since things behind #
are not sent to server.
This task also includes modifying server config so for any path server returns root path index.html. Otherwise ipfs won't find a file.
Also, if detected using other domain than namebazaar.io (or localhost), front-end should fallback into #
urls again. Because if site will be accessed via ipfs like for example: https://ipfs.io/ipfs/QmVe5ebTzNjDcpL6ycRga2Vyk66cVZksTzkxMaHo9z6795/offerings
, it won't find a file. Must be https://ipfs.io/ipfs/QmVe5ebTzNjDcpL6ycRga2Vyk66cVZksTzkxMaHo9z6795/#/offerings
Subdomain leasing for ENS domains will be HUGE. Please add to Name Bazaar
When viewing "Sold" offerings 2 extra options should be added into Order By select bar:
name-bazaar.ui.utils/offerings-sold-url
should contain these params.Select field already has those 2 options, just rename them to:
Implement sanity checks for auction properties as suggested in audit https://gist.github.com/Arachnid/3416e5a85b5b67eb9cdfa2252a5e28d9#lack-of-sanity-checks-on-auction-end-time
Auction end time can't be longer than 4 months.
Time Extension can't be longer than duration from now to auction end time
also add some simple tests please
In commit 59bd456 were addressed all outstanding issues from audit.
Could you please perform small audit on contracts before we send it back to Nick for final look. Also please add 1 new test scenario I'll describe below.
Issues that were addressed:
Now we use very thin proxy contract Forwarder, which proxies all functions to deployed instance of BuyNowOffering.sol or AuctionOffering.sol, which are singletons used only for logic, not storing data. You can read more about this pattern here
Since we don't use Solidity's libraries, we can use modifiers in offering contract.
This has been changed throughout the app
This was solved by putting placeholders into offering contracts, which will be replaced after compilation. This way those addresses don't have to be set on contract initialisation run by user, therefore user doesn't have to pay gas for it.
This was solved by removing reusing pending returns for new bids
Instead of passing registrar contract address, now we access it's address by ens.owner(namehash("eth")), which should stay up to date even if registrar address changes in the future.
This was solved by adding onlyWithoutNewOwner
into reclaimOwnership
function.
Offering registry has now variable isEmergencyPaused
, which can disable buy/bid/finalize function on all offerings at once. Please write test scenario when isEmergencyPaused
is used.
So currently there are hardcoded namebazaar domains in district0x lib code.
name-bazaar/src/district0x/ui/utils.cljs
Line 28 in d39fdcc
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.