Giter Site home page Giter Site logo

district0x / ethlance Goto Github PK

View Code? Open in Web Editor NEW
694.0 62.0 125.0 23.67 MB

Ethlance is the first job market platform built entirely on the Ethereum blockchain. Free to use forever!

Home Page: http://ethlance.com

License: GNU General Public License v3.0

Shell 0.27% Clojure 55.09% HTML 0.04% JavaScript 2.97% Makefile 0.08% Solidity 4.09% Hack 9.94% PHP 3.78% Less 23.38% Procfile 0.03% Dockerfile 0.34%
ethereum blockchain clojurescript freelance solidity district

ethlance's Introduction

Ethlance V.2 (Newlance)

CircleCI

Ethlance Version 2 is Currently in Development and is subject to change before final release

Development

Prerequisites

  1. Node.js >= 16.15.1
  2. Java JDK >= 18 (for Clojure)
  3. Babashka
  4. PostgreSQL (tested with 14.6)
  5. IPFS daemon
  6. Ethereum testnet (e.g. ganache)

Running the system

  1. Start IPFS
  2. Start ganache
  3. Migrate Solidity contracts to testnet: npx truffle migrate --network ganache --reset
  4. Start server build bb watch-server
  5. Start server (to serve the API) bb run-server
  6. Start UI build bb watch-ui
  • this also starts serving the UI assets & smart contract assets on port 6500

First steps, showing example data

In order for the front-end to be able to have the JWT token (kept in LocalStorage), you must sign a transaction. Currently it can be done manually. Open REPL for UI:

lein repl :connect 54200
(shadow/repl :dev-ui)
(in-ns 'ethlance.ui.event.sign-in)
(re/dispatch [:user/sign-in])
  • this will show a pop up and using MetaMask you can create a transaction
  • after doing this successfully the UI graphql requests will have proper Authorization: Bearer ... header

Then to generate some example data you can use server REPL:

lein repl :connect 54100
(shadow/repl :dev-server)
(in-ns 'tests.graphql.generator)
(generate-for-address "0xafcf1a2bc71acf041c93012a2e552e31026dfeab")
  • for that the test namespace must be included in the server build (e.g. by adding [tests.graphql.generator :as test-data-generator] to ethlance.server.core)
  • alternatively you can submit the data manually through the forms

Tips & troubleshooting

Postgres setup

Start postgres console psql -d postgres

CREATE USER ethlanceuser WITH ENCRYPTED PASSWORD 'pass';
CREATE DATABASE ethlance WITH OWNER ethlanceuser;
-- alternatively if you created the database earlier, give access with:
GRANT ALL PRIVILEGES On ethlance TO ethlanceuser;

IPFS Server

Might require additional configuration for CORS if IPFS is running on a different host

ipfs config --json Gateway.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "GET", "POST", "OPTIONS"]'
ipfs config --json Gateway.HTTPHeaders.Access-Control-Allow-Origin '["*"]'
ipfs config --json Gateway.HTTPHeaders.Access-Control-Allow-Headers '["X-Requested-With"]'
ipfs config --json Gateway.Writable true

Building & deployment

1. Smart contracts

The ethlance smart contracts should (for now) be deployed manually. As a result of the compilation process, the environment specific clojure files with contract addresses get written (e.g. shared/src/ethlance/shared/smart_contracts_qa.cljs for QA) and must be committed to git to make them available for deployment of browser & server applications.

During clojure application deployment (browser, server), the contracts must only be compiled, which will generate JSON ABI files under <ethlance-root>/resources/public/contracts/build/

Compilation:

  1. ETHLANCE_ENV=qa npx truffle compile (replacing the network with one suitable for the env)
  2. This generates ABI JSON files under <ethlance-root>/resources/public/contracts/build/
  3. Server app needs to access them during runtime:
  • configured via [:smart-contracts :contracts-build-path]
  1. UI (browser app) needs them available: should be served by Nginx (or your web server of choice)
  • get loaded from urls like http://d0x-vm:6500/contracts/build/TestToken.json

2. Server (/server)

To build Server (consists mainly of graphql API):

  1. The following ENV variables need to be set:
  • export ETHLANCE_ENV=qa
  1. Compile with clj -A:dev:shadow-clj release dev-server
  • will result a single file in out/ethlance_server.js (and accompanying ethlance_server.js.map source map)
  1. Before running it the smart contract ABI JSON files need to be in a location defined in the EDN file ETHLNCE_CONFIG_PATH at EDN path [:smart-contracts :contracts-build-path]
  • if it's a relative path, it gets resolved in relation to where the server process gets started

Running server:

  1. Earlier the server config was compiled into the generated JS file. Now it will be loaded during runtime (at application startup) from the variable specified under :config :env-name. As for now it is ETHLANCE_CONFIG_PATH.
  2. Also earlier the UI (browser app) config was baked into the compiled JS file for the UI. Now it gets served via /config endpoint from a location pointed to ENV variable UI_CONFIG_PATH (contents loaded at run time from the file system). Thus, starting the server:
  • export ETHLANCE_ENV=qa
  • export SERVER_CONFIG_PATH=/path/to/server-config-qa.edn
  • export UI_CONFIG_PATH=/path/to/ui-config-qa.edn
  • node out/ethlance_server.js

3. Browser (/ui)

  1. The following ENV variables need to be set:
  • export ETHLANCE_ENV=qa
  1. Compile with clj -A:dev:shadow-clj release dev-ui
  • the generated JS file (single) will be under <ethlance-root>/ui/resources/public/main.js
  1. To serve the web page, configure the web server to serve the files under <ethlance-root>/ui/resources/public
  • there are some other files, like CSS, JS and index.html that the web server needs to serve too
  1. The web server must also serve the ABI JSON files generated in 1. Smart contracts
  • for that, they can be copied from the build step or re-compiled and moved to where the web server can serve them
  • the expected HTTP path will be /contracts/build/<ABI JSON FILE>.json (e.g. /contracts/build/Ethlance.json)

Contributing

Anyone is welcome to contribute to the ethlance project, here are some brief guidelines:

  • Make sure to squash your commits
  • Reference issue numbers in your pull request
  • Rebase your changes on upstream (git remote add upstream https://github.com/madvas/ethlance.git) master before pushing (git pull --rebase upstream master)
  • Make changes in a separate well-named branch in your forked repo like improve-readme

Overview of workflows

Here's a brief overview of the sequence of actions that different user types can take to create, find and arbiter jobs.

  1. User arrives to the home page
  • http://d0x-vm:6500
  • picks which profile to create (freelancer = candidate, employer, arbiter)
  1. This takes the user to the sign-up page
  1. Employer (having first filled in employer data)
  • http://d0x-vm:6500/jobs/new
  • user can create new job by filling in the form
  • creating a new job requires sending a signed transaction together with the initial funds
  • smart contract method Ethlance#createJob is called and a new copy of Job contract gets deployed
  1. In case the employer invited arbiters during job creation /jobs/new
  • First: arbiter must send their quote (how much they want for their service for this job)
    • ... where can they do it (one or more pages)?
    • script helper: tx-workflow-fns-server-repl/set-quote-for-arbitration
  • Second: employer must accept the quote
    • ... where can they do it (one or more pages)?
    • script helper: tx-workflow-fns-server-repl/accept-quote-for-arbitration
  1. Employer can now invite candidates to participate in the new job
  • NB! implement & provide link
  • results in Job#addCandidate contract send
    • script helper: tx-workflow-fns-server-repl/add-candidate
  1. Candidate can search for available jobs
  1. Candidate chooses a job of interest from search results. To work on it, needs to send proposal
  1. All users can view job contract page at
  1. Candidate can create invoices (for any of their jobs)
  1. Candidate can then raise dispute
  • after raising dispute, arbiter can resolve it on the same page (http://d0x-vm:6500/invoices/new)
    • resolving dispute results in tokens getting transferred according to the resolution amount
  1. Employer can pay invoices
  • ... (add link, implement if needed)

ethlance's People

Contributors

analyticbastard avatar benzap avatar bradymck avatar fbielejec avatar foopang avatar happyrobotstudio avatar jpmonettas avatar madis avatar madvas avatar oliversimon avatar sm47916 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ethlance's Issues

Can't upload my profile picture

Hi,

I created a Freelancer profile, when I created the profile I couldn't change de default profile picture.
I can't change it now when I click on the profile picture.

Is it normal ?

Failed job posting due to gas is not explained

What

I tried to make a job posting, but was unsuccessful. I was redirected to Job page without explanation. I thought I was charged ETH for the transaction, but the contract never appeared.

Hypothesis

When I initially paid for the contract, the gas was too low, so the contract was unsuccessful. The
"create job" page was stuck in a "loading" state after the failed contract, so I refreshed the page. After refreshing, I re-entered the information and then submitted. After adjusting the gas, I was successfully redirected to the "My jobs" page.

Issue

The contract that was successful, but didnt result in a job can be seen with this transaction: 0x7f442b0d4d330023e907ed7fdca93c858aa21c476c5f29db7094617cf7385662.

The contract that was failed, and forced me to restart can be seen with this transaction.
0x0bc10f232919ba1e6f8c75d7f458ca83a4db5459a5d805739a22b63b6afe0458

Actual issue

As seen in the first contract link, the failed contract was "Out of gas". This was never addressed on the front-end and led to a confusing UI.

Improve hyperlink unfurls

When posting job links (e.g. https://ethlance.com/#/job/354) into clients like Slack, Discord, etc. the unfurl that is displayed only contains generic information for the Ethlance website.

At minimum, we should change these unfurl patterns to accommodate:

  • Job postings, including the title of the job post, truncated description, and possibly the employers logo. Any other relevant metadata that can be formatted to fit is welcom.

As a bonus, we should also accommodate:

  • Freelancer profiles, including their headshot and profile description and any other relevant metadata (join date, rating?)
  • Employer profiles, including their logo and a description of the company

Escrow Service

Is Escrow Service something that you offer ? It makes total sense to protect both the buyer and the seller.

HTTPS Switch is URGENT

Hello, a site running on http and not https, seems like a lack of care for security, which severely degrades credibility of the platform.

This should be something you proceed to do ASAP !

"First name" calculation is slightly off

Not sure where all on the site freelancer names get abbreviated as first-name-only, but at least on the toolbar, it's a bit weird when I write my name formally as first letter of first name, full middle name:

screen shot 2017-02-21 at 11 12 39

Just a minor gribble though. Maybe it would make sense to take every word up until the last, rather than just the first word? Seeing g. nicholas everywhere instead of g. feels a bit less like a robot is trying to guess what to call me.

(Ideally, it'd be nice to have a separate field for "friendly name" or whatever, because, for instance, the name I use formally is not the same as the name I tell people to call me)

-Nick

Next Page of Freelancers

If I enter the site for the first time (without being logged in) and I click on "find candidates" and then go to next page without specifying a skill it says "no more candidates are available".

Statistics

Where can we see how many users ethlance has ?

Improve code documentation

I think ethlance is a shining example of a decentralized market platform. It is inspiring me to try to create one of my own, but unfortunately I'm having a hard time learning from the codebase because of lack of comments.

Can't see messages sent to candidates

Hello!
I have candidates applied for my job.
I went to a job proposal screen (https://ethlance.com/#/job-proposal/1080), selected "Send message" tab, entered a message, and clicked "Send".
But I can not see my message in the history.
Chat at the top contains only candidate's message.

ethlance-cant-see-sent-message-in-history

I tried this for 2 candidates, with the same result: can't see my sent message.

I have not accepted the job proposals yet.

Do I have to accept the proposal to start chatting?

Connecting Github account fails

I have an existing freelancer account on Ethlance, from before GH-connecting was implemented. After connecting my Github identity, the "Save User" button fails to provide any feedback, and I notice a JS console error:

    at r (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:6703:24032)
    at Object.c [as encode] (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:6703:24748)
    at Object.l [as fromUtf8] (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:6700:17541)
    at i.f [as _inputFormatter] (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:6700:8923)
    at i.encode (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:6700:13941)
    at chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:6700:6039
    at Array.map (native)
    at d.encodeParams (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:6700:6012)
    at s.toPayload (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:6701:5246)
    at s.sendTransaction (chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/scripts/inpage.js:6701:6016)
r @ inpage.js:6703
c @ inpage.js:6703
l @ inpage.js:6700
f @ inpage.js:6700
i.encode @ inpage.js:6700
(anonymous) @ inpage.js:6700
d.encodeParams @ inpage.js:6700
s.toPayload @ inpage.js:6701
s.sendTransaction @ inpage.js:6701
s.execute @ inpage.js:6701
UR @ app.js?v=1.2.2:1381
CX.o @ app.js?v=1.2.2:1563
CX.I @ app.js?v=1.2.2:1563
q.h @ app.js?v=1.2.2:627
m8 @ app.js?v=1.2.2:2228
(anonymous) @ app.js?v=1.2.2:1539
nW @ app.js?v=1.2.2:1523
zW @ app.js?v=1.2.2:1525
g.Uh @ app.js?v=1.2.2:1536
FW @ app.js?v=1.2.2:1527
g.Xh @ app.js?v=1.2.2:1531
HW @ app.js?v=1.2.2:1528
(anonymous) @ app.js?v=1.2.2:1533
g.Sh @ app.js?v=1.2.2:1535
DW @ app.js?v=1.2.2:1526
(anonymous) @ app.js?v=1.2.2:1532
b.port1.onmessage @ app.js?v=1.2.2:1287

Using MetaMask

Implementing Coinbase app store redirect for mobile users who don't have a wallet present

Using re-frame events provided by https://github.com/district0x/district-ui-window-size and https://github.com/district0x/district-ui-web3

Depending on whether ethlance will work with district-ui-web3, I can fallback to cljs-web3 for determining web3 presence.

Suggested Enhancement involves first checking if a mobile device is accessing ethlance without using a software wallet. If it is determined that they have no software wallet, a modal should appear suggesting the use of a supported software wallet for their mobile device (Install Coinbase from the App Store, Play Store!)

Move contract data from state into events/IPFS

In many places, such as:

arbiterData.paymentValue = paymentValue;
arbiterData.currencyType = currencyType;
arbiterData.paymentType = paymentType;

bidOption = _bidOption;
estimatedLengthSeconds = _estimatedLengthSeconds;
includeEtherToken = _includeEtherToken;
isInvitationOnly = _isInvitationOnly;
metahash = _metahash;
rewardValue = _rewardValue;

amountRequested = _amountRequested;
dateCreated = now;
dateUpdated = now;

fromUserAddress = feedback.fromUserAddress;
toUserAddress = feedback.toUserAddress;
fromUserType = feedback.fromUserType;
toUserType = feedback.toUserType;
metahash = feedback.metahash;
rating = feedback.rating;
dateCreated = feedback.dateCreated;
dateUpdated = feedback.dateUpdated;

We're storing data in smart-contract state unnecessarily, because it's nowhere used for trustless logic within smart-contracts. All data that doesn't need to be accessed from other smart-contracts, should be passed to an event or stored as IPFS hash and server will reconstruct it from there. This way lot of gas will be saved. You can actually combine event and IPFS approach into the one, by not even storing IPFS hash in smart-contract, but just passing it into event. You can learn more about this approach here:
https://medium.com/@childsmaidment/stateless-smart-contracts-21830b0cd1b6

Interest in the deploy

Hi madvas, can you show the deploy workflow on Ethereum public blockchain and IPFS, i think the automate deploy script may be very useful to others developing dapps.

Change the name

The site is excellent, not a single complaint. I used it to post a job.

I was just thinking, before this thing takes off and everyone knows who you are (because that will happen), you should change the name of the site. eth-anything is starting to get really old, and it will soon sound very old-fashioned. Branch out to a name that doesn't have the word 'eth' in it. I'm pretty sure you'll be glad you did.

You can close this issue if you want. It's just a suggestion.

Odd transaction (incomplete)

Hi there. I am attempting to register as a freelancer.

However, upon sending the appropriate funds via metamask, I was being told that my transaction was undervalued.

So I sent a preposterous amount of gas with the value from ethstats.

Here is the transaction: https://etherscan.io/tx/0xdf105b80480eedcdc4d6f570655f9bc8fa2c18106e9434d84367a9f9375be609

For some reason, the value is slated at 0ETH, and has run out of gas and I have not received a refund.

Also, the website itself simply kept displaying the loading screen without telling me of any error.

Sending a message to candidates

Perhaps there's something I couldn't find, how can I message candidates that I find appropriate to let them know I want to work with them ?

New Ethlance home page changes

  1. Add third button Become an Arbiter
    image

  2. Let's change "No restrictions and free membership" to "No restrictions, no fees and free membership" (icon might need some update as well). And then we'll replace "0% service fees" with "Decentralised dispute resolution, anyone can become an arbiter" (new icon will be needed)
    image

  3. Add third tab "Arbiter" with following steps: Complete your profile, Receive invitation for job supervision, Investigate the problem, Resolve the dispute, Receive Ether, Leave feedback
    image

  4. Add third button Become an Arbiter
    image

How you make money

Hi,

Just wanted to know how you make money with Ethlance ?
Is it a "pure altruism-based" application ?

UI does not detect changing of account in metamask

UI does not recognize if I select another account in metamask. You need to manually reload the page so it picks up the new selected account.

Metamask only ever exposes one account (web3.eth.accounts[0]) to the dapp. Currently there is no nice way of getting a callback or similar when the account changes. Instead a dapp needs to watch accounts[0] for changes. Code sample from the metamask developer faq:

var account = web3.eth.accounts[0];
var accountInterval = setInterval(function() {
  if (web3.eth.accounts[0] !== account) {
    account = web3.eth.accounts[0];
    updateInterface();
  }
}, 100);```

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.