morkeltry / gap-microfinance Goto Github PK
View Code? Open in Web Editor NEWGAP microfinance frontend and Solidity prototype
GAP microfinance frontend and Solidity prototype
Interrogates IDBox blockchain to find if borrowerEthAddr is registered.
While no access to IDbox blockchain, use dummy structure : #8
Takes ( borrowerEthAddr, phoneNo, callback ) as params.
phoneNo is accepted only for compatibility with future functionality.
Will eventually call callback with a repaymentSchedule as params,
but for now, will just call callback with a truthy or falsey value.
Either use media query to change font size,
or represent in format 0x1234....cdef.
Path should be relative!
Set up express,
Get a server running which is capable of serving endpoints and has routes for the endpoints in #5, #6 #8, #24 & #25 plus a route /sms for Twilio webhook. Comment out if unused.
We will probably need static pages served as well.
Liase with @jignasheth407 to find out if using React, file structure, etc.
EDIT - Looks like she's aiming to use Bootstrap 3.
For demoing - In finished product, this should be done using IDbox.
USE SECURITY!
Preferably JWT, but at the least, IP whitelist or password check.
-this endpoint will be open to the world, even on localhost.
The results will not look like the IDbox blockchain in any case, so we can use any data structure and means of storage, if the dummy isIdBoxregistered()
#18 matches the structure.
It is worth developing a hashing mechanism so that phone numbers are not discernable from the blockchain (though this is probably impossible is we keep the functionality of being able to search by ethAddress).
So that redirects always have the same status regardless of external changes.
Is cachebusting easy in jade?
Using the proper TTLs may be better.
mySQL connection
con.connect(function(err) => stuff)
throws:
Error: Cannot enqueue Handshake after already enqueuing a Handshake.
after attempting to connect more than once.
Move connection to start of file, or else test for connection before attempting connect.
Mock of #23,
checking db for loan offers.
Accepts borrowerEthAddr as params,
responds with empty object if no offers or, if offer exists,
{ borrowerEthAddr,
lenderName,
amount,
duration, // = endDate - startDate
tx }
where
tx = {
from: borrowerEthAddr,
to: contractAddr, // use env2 to set this as app constant - '0x12345' is fine
gasPrice: "9000000000",
gas: "85000",
data: ""
};
as in #5
For small screens.
V1: First make decent on 640px width
V2: Make it responsive
In onbording-3,
Implement most basic version - just returns 20% true; 80% false
How to set Status Callback URL for Twiml App? i mean can we use one status Callback URL for Video Calling, Voice Calling or need to set separately?
write populate functions, dummy at first.
ids for all input elements used. If poss, match to ids in response objects for DRYness
add shading overlay / spinner logic.
Performs GET request to /registeroffer, passing lenderEthAddr as parameter
and expects to receive an array of objects { id; startDate; endDate; amount; duration; repaymentSchedule; lenderName; lenderEthAddr; borrowerEthAddr; txWithdraw; txRegister}
representing offered loans in response.
(Some properties may be missing from the response object)
Don't use the red background. Please use something more like the login page.
Display text part of logo at top of screen.
The box at the top contains ' Hi, lenderName', with lenderEthAddr below it in the box in a lighter font-color. Logout should be below that in the box.
List returned objects with:
/historyimg?borrower=0x76543
where 0x76543 is borrowerEthAddr. The SVG will be a bar chart, but you can use any SVG, as long as the request it makes for the file includes a variable querystring depending on the previously retrieved data.None of the items in this list need a heading (like amount, or repayments) - the data is enough.
The list should be scrollable at the bottom in case it contains a lot of items.
Once scrolled, the top of the visible list should show a 'Top' button to scroll the list back tot he top.
The bottom part of the screen should be a button to an offered loans page (don't build that page, just make the button) and this button should always be visible at the bottom of the screen.
Interrogates blockchain to find if borrowerEthAddr has a current loan.
Takes ( borrowerEthAddr, callback ) as params.
Will eventually call callback with a repaymentSchedule as params,
but for now, will just call callback with a truthy or falsey value.
The submit button ('Register') will either take user to auth page, or to loans flow branching logic, depending on the result of isIdBoxregistered(ethAddr, phoneNo).
isIdBoxregistered() is asychronous and takes a callback as its third parameter - which will be called with either a truthy value, or false.
If truthy, user goes to loans flow branching logic,
if false, user goes to auth page
This check can be done on the click/ submit event of 'Register', or before rendering auth page, as appropriate for the framework.
Route to one of the 3 possible loans pages: repayments, eligibility and apply.
Note this is a change from yesterday's flow diagram.
Create dummy functions hasActiveLoan()
and hasLoanOffer()
and mock these functions so that they return (for testing purposes)
Make 2 async calls to the functions and await results.
if `hasActiveLoan (ethAddr)
\\ route to repayments
else if hasLoanOffer (ethAddr)
\\ route to apply
else
\\ route to eligibility
Show attractive loading screen while waiting for results (eg GAP graphic from upwork)
and distribute secrets on gitter
We will discuss this, but at first guess:
repaymentSchedule should be an stringified object with numbered keys (cumulativeDays) having properties cumulativeAmount.
So a loan of QI100 issued on the 4th with repayments due of QI25 on the 9th, 14th, 19th and 24th of the month would have
repaymentSchedule = {
'5': 25,
'10': 25,
'15': 25,
'20': 25
}
to reduce on-chain processing.
Makes call to dummy function getHistory(ethAddr), calls both populate(creditIndication()) on the response, which is expected to be an array of strings.
Renders all elements, constant height
Credit History shows 'None' until populated.
large middle element shows GAP background graphic until populated (ie once eligibility is a number)
Apply button has 0.75 opacity until populated, but is always active unless deactivated (or, if using top-down state, if eligibility===0)
write creditIndication() function which takes either an array of strings, 0 or -1 as argument and returns if array: array.length*150
if zero: 100
if -1 : -1
write populate() which populates middle element as shown in flow diagram and sets Apply opacity to 0.75 if eligibilty is -1, 1.0 otherwise
For Amber demo today!
Especially for small mobile screens.
Everything should function and be presentable (no horizontal scroll bars, no elements overflowing outside their visible sections/ backgrounds) on all screen sizes, even 240x320
I suggest name the endpoint /offers
Accepts as params the fields from Apply page form #14, plus borrower eth address,
Compare these to lender's settings from db.
Choose a lender (based on preferences?)
EDIT:
If borrower has a loan offer in db already, use that.
/EDIT
If borrower meets criteria for a loan and does not already have anything outstanding on a loan
store details as an 'offer' in db and
respond with an object containing tx: a smart contract transaction object with as many mandatory fields filled as poss, AND a unique nonce.
See transaction structure and comment.
data field is a todo for later #21.
Liase with @jignasheth407 #14
Set an environment variable CONTRACT_ADDR in .env and use this in tx as to:
Assume mySQL is installed and a database user has been created and has permissions.
Make a .js script which uses the existing user details, stored in a .env file and populates the mySQL database from the queries in /server/database/db_build.sql
The code can be copied direct from /server/database/db_build.js and modified for mySQL.
In onbording-3,
Return via callback, linked to setTimeout().
If poss, take timeout value as page param to allow bookmarking.
Interrogates blockchain to find if borrowerEthAddr has a loan offered.
Takes ( borrowerEthAddr, callback ) as params.
If loan offer exists, calls callback with (amount, duration, lenderEthAddr).
Otherwise does nothing.
If short of time will be mocked using an endpoint
Text as in flow diagram.
Before render, make async call to hasLoanOffer(ethAddr)
If this returns an array, populate page with result, expecting:
result [2] to be Lender Name,
result [1] to be Duration in days,
result [3] to be Amount
Render form with
inputs:
buttons :
Take this Loan and Reject buttons occupy the space on screen which was previously taken by Check Loan Offers.
page requires a populate() function which:
And make it conditional upon postSendValidate.
which stores:
and emits:
Accepts as params: borrower's eth address,
Responds with: details of the loan previously accepted by borrower.
Should map a repaymentSchedule object into an array of objects {date, amount}
Do not include loans where fullyPaid == true;
If not unpaid loans can be found, returns empty array.
Currently /signup and /info redirect straight to /loan_offer where user is IDbox registered.
We will need to check if they already have a loan and redirect to a route for repyaments (check what already exists for this)
Use either top or bottom half of logo and/or background it.
Ensure values in amount prepended with 'QI '
Change 'Your Story', in consultation with Helena/ Ola if necessary.
Colour 'Check Loan Offers' and move upwards level with 'Story' textbox
Appropriate relative shading for 'Check Loan Offers' / 'Take This Loan' depending on populate()
Add Lender info
endpoint accepts as params:
lenderEthAddr
and, optionally,
{ id; startDate; endDate; duration; repaymentSchedule; lenderName; lenderEthAddr; BorrowerEthAddr}
OR
offers: stringified array of { id; startDate; endDate; duration; repaymentSchedule; lenderName; lenderEthAddr; BorrowerEthAddr}
objects.
If only lenderEthAddr
provided, then retrieve an array of offers made by that lender from db, excluding those which are also in accepted loans.
If more fields than lenderEthAddr
are provided, wrap params object in array.
If offers
passed, unwrap into array
Filter array keeping only objects where
all of { duration; lenderEthAddr; BorrowerEthAddr }
provided or
all of { startDate; endDate; lenderEthAddr; BorrowerEthAddr }
provided
For each object, calculate startDate; endDate; duration
if missing.
For each object, add two properties txWithdraw
& txRegister
which are clones of each other:
= {
from: borrowerEthAddr,
to: contractAddr, // use env2 to set this as app constant - '0x12345' is fine
gasPrice: "9000000000",
gas: "85000",
data: ""
};
as in #5
and respond with stringified resulting array
Page receives ethAddr and phoneNo.
The Done button should white fade the whole screen, except the button itself and
call isIdBoxregistered(ethAddr, phoneNo, branch)
where branch is a callback taking one parameter.
If that parameter is true, it causes user be taken to loans flow branching logic
If false, white fade is removed, and the middle text 'but you need to link your IDbox phone number' is changed to 'your phone number has not yet registered with IDbox'
isIdBoxregistered() can be called on the click/ submit event of 'Done' or, alternatively, before rendering the page, as appropriate for the framework.
(In onbording-3)
Await connection over websocket via (result of /ws-get-addy || 127.0.0.1 ) + /ws-listener.
If no connection, fallback to random.
If possible, create websocket listener as separate npm process.
while /retrieveloans responds
to be accessed from server.
Stores:
ethAddress -> (current) phoneNo
Emits:
ethAddress -> phoneNo
Need to brainstorm on protecting personal details.
For multiple lenders, this may require choosing between multiple one-of-many hash secrets and a shared lender hash secret.
First render our beautiful welcome page,
then run redirectIfOnboard():
Check for Metamask (if (web3)
will do this. If you don't have Metamask, do the check, but spoof the variable as true or false for testing)
set ethAddr = web3.eth.accounts[0]
- if you don't have Metamask, then spoof with ethAddr = '0x654321';
We will use ethAddr all through both flows, so if not using state, this must be passed from page to page.
function redirectIfOnboard() {
if (web3) {
ethAddr =web3.eth? web3.eth.accounts[0] : '0x654321';
/// route to phone number page
}}
For demo purposes set a listener for click anywhere on screen, which sets web3= true
then calls redirectIfOnboard(). But comment out (don't delete) the listener once tested - we will use it for later testing.
remove hardcoded table
style responsive table
GET from endpoint /retrieve in #6 (liase with @Parissai ), passing ethAddr as params
Render all elements constant height - no text in Repayments and Repayment Instructions until populated.
Repayments will be populated with response of GET, which will include repayments: an array of objects {date, amount} (Amount is in QI so 25 -> 'QI 25')
Refresh links back to loans flow branch logic
Repayment Instructions will be populated with a button named 'Send to X' where X is the property tx.to
from the result of the GET. This button calls a function repay (tx);
Write mock repay function :
setTimeout ( {\\ link back to loans flow branch logic as if Refresh was clicked}, 500)
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.