Jackson Kelley

ETHLend & uPort, A Match Made in Heaven

In my previous write up I mentioned that we would dive deeper into what a possible block chain credit score would look like. Well, in order to have a credit score, you must first have an identity with which to attach that credit score. It therefore seems the most logical place to start in our investigation of credit scoring is identity. Today, we’ll be using uPort to create a loan on ETHLend using our uPort identity. For the sake of brevity, I’m going to assume you’ve followed the steps in the uPort devPortal and have an identity. I’m also going to assume you’re familiar with how ETHLend works.

uport-connect

To start, we’re going to create a quick and dirty node.js cli for illustrative purposes which we’ll use to connect our uPort identity to:

const uport_lib = require('uport-connect');   
const qrcode = require('qrcode-terminal');      
const SimpleSigner = uport_lib.SimpleSigner;   
const Connect = uport_lib.Connect;      
const uport = new Connect('ETHLend Integration', {       
  clientId: 'UPORT_APP_ADDRESS',       
  network: 'rinkeby',      
  signer: SimpleSigner('SIGNING_KEY'),              
  uriHandler = uri => qrcode.generate(uri,{small:true})  
})    
uport.requestCredentials(['name'])
  .then(userProfile => {  console.log(userProfile);  })    
  .catch(err => {  console.log(err)  })

You’ll obviously need to npm install uport-connect as well as qrcode-terminal.

Put the above code into a file (may I suggest ETHLendRocks.js?) and run:

node ETHLendRocks.js

You should see a QR code generated on your terminal. Scan it, and grant your uPort mobile app access to your uPort identity credentials. You should see your uPort profile data logged to the terminal. Now that we have an identity, we can store different attributes about this identity using IPFS and the uPort-registry package.

uport-registry

In order integrate uport-registry we need to do a bit of extra set up to our existing application:

const uport_lib = require('uport-connect');
const MNID = require('mnid'); 
const qrcode = require('qrcode-terminal');
const registryArtifact = require('uport-registry'); 
const Contract = require('truffle-contract'); 
const Registry = Contract(registryArtifact);  
const NUMBER_OF_LOANS = 10; //random number of loans of illustration
var registryInstance;  
const SimpleSigner = uport_lib.SimpleSigner;   
const Connect = uport_lib.Connect;      
const uport = new Connect('ETHLend Integration', {       
  clientId: 'UPORT_APP_ADDRESS',       
  network: 'rinkeby',       
  signer: SimpleSigner('SIGNING_KEY'),
  uriHandler = uri => qrcode.generate(uri,{small:true})  
})   
 
const web3 = uport.getWeb3();   
Registry.setProvider(web3.currentProvider); 
Registry.deployed()
  .then(reg => {  
    //set the global registryInstance variable to access anywhere in the app
    registryInstance = reg;
  });    
	 
uport.requestCredentials(['name'])   
  .then(userProfile => {  
    //decode the users address based on which network they're on   
    let addressPayload = MNID.decode(userProfile.address);     
    return registryInstance.set('Open Loans',addressPayload.address,NUMBER_OF_LOANS,{from:addressPayload.address});    
  }) 
  .catch(err => {    console.log(err)  })

Using the registryInstance.set parameters we can put any sort of financial data we want to store about a uPort identity. We can then retrieve it using the registryInstance.get() method:

uport.requestCredentials(['name'])
  .then(userProfile => {     
    let addressPayload = MNID.decode(userProfile.address);     
    return instance.set('Open Loans',addressPayload.address,NUMBER_OF_LOANS, {from: addressPayload.address});   
  })
  .then(tx => {     
    const subject = tx.logs[0].args.subject;
    instance.get('Open Loans', subject, subject)
      .then(value => {      
        console.log(hexToString(value));     
      })   
  })
  .catch(err => {     
    console.log(err)   
  })  
	
function hexToString (hex) {     
  var string = '';     
  for (var i = 0; i < hex.length; i += 2) {       
    string += String.fromCharCode(parseInt(hex.substr(i, 2), 16));    
  }     
  return string; 
}

Obviously, this can be used to store information about a uPort identity any time they do anything in an ETHLend dApp. How many times they’ve defaulted, how many loans are currently open, and what value they’re for, are a few examples.

ETHLend

To integrate this uPort identity into the ETHLend ecosystem we simply need to create a contract object with whatever contract we’re interested in interacting with:

const web3 = uport.getWeb3();
const CreateLedgerContractObj = () => {      
  let LedgerContractABI = web3.eth.contract(LEDGER_CONTRACT_ABI);
  let LedgerContractObj = LendingContractABI.at(LEDGER_CONTRACT_ADDRESS);      
  
  return LedgerContractObj;  
}    
const LedgerContract = CreateLedgerContractObj();

In this case I’ve chosen to use ETHLend’s Ledger contract. So you’d fill in the LEDGER_CONTRACT_ABI and LEDGER_CONTRACT_ADDRESS with whichever smart contract you’re interested in interacting with.

Once we have the smart contract object, we can call methods on it inside the .then() block of the requestCredentials call:

uport.requestCredentials(['name'])
  .then(userProfile => {     
    let addressPayload = MNID.decode(userProfile.address);     
    const usersEthereumAddress = addressPayload.address;     
		makeLoanRequest(usersEthereumAddress, 100);    
  })   
  .catch(err => {     
    console.log(err)   
  })  
	
const makeLoanRequest = (address, loanAmount) => {   
  LedgerContract.createNewLendingRequest({     
    from: creator,
    value: loanAmount,     
    gas: 2000000    
  }, (err,txhash) => {     
    if(err) throw err;           
    waitForMined(txhash, {blockNumber: null},          
    pendingCB() => {              
      console.log('waiting for loan request to be mined...');         
    },          
    successCB() => {       
      console.log('your loan\'s transaction hash is:',txhash);       
      incrementIPFSLoanCount(address);       
      incrementIPFSOpenLoanAmount(address, loanAmount);       
      //any other financial data you'd like to track can be get and set here...     
    }          
  }) 
}  
const incrementIPFSLoanCount = (subject) => {   
  instance.get('Open Loans', subject, subject)
    .then(value => {     
      instance.set('Open Loans', subject, value + 1, {from: subject})    
  }) 
}  
const incrementIPFSOpenLoanAmount = (subject, openedLoanAmount) => {   
  instance.get('Open Loan Value', subject, subject)
  .then(value => {     
    instance.set('Open Loans', subject, value + openedLoanAmount, {from: subject})    
  }) 
}

Here I’ve illustrated how one would store the number and amount of open loans made by a uPort identity at the time of loan creation, but any number of metrics can be used and any point in a loaning and borrowing process.

Developers

This brings me to my final point. If we’re going to use IPFS as an open, transparent data store, then the ETHLend smart contract is going to need to update the data associated with the uPort identity via IPFS as well, depending on various conditions known only to the ETHLend smart contract. Currently this is not implemented.

If you’re a developer and you’re interested in developing smart contract code, this is a perfect opportunity to make your mark! Check out the ETHLend repo, and see if you can get your pull request merged into the master branch, or, feel free to get in touch with ETHLend via the many social media channels:

https://twitter.com/ethlend1

https://www.facebook.com/ETHLend/

https://www.instagram.com/ethlend1/

https://steemit.com/ethereum/@ethlend

uPort is always interested in hearing from developers as well and in fact were instrumental in making this article happen.

https://www.uport.me/

https://github.com/uport-project

https://gitter.im/uport-project/Lobby

More by Jackson Kelley

More Related Stories