Overview

After the user completes the authentication process, they have a token. They now pass it to the application to "login", which tells the application which Mobius user account to withdraw MOBI from (the user public key) when a payment is needed. For a web application, the token is generally passed in via a token request parameter. Upon opening the website/loading the application, it checks that the token is valid (within time bounds, etc) and that the account in the token has added the app as a cosigner so it can withdraw MOBI from it.

Walkthrough

Create DApp Instance##

When working with the dapp object, we need to create a new instance. The same steps were followed in the Accounts Walkthrough .

/** 
 * @param {string} APP_SECRET_SEED - App developer secret seed
 * @param {string} USER_PUBLIC_KEY - User public key
 * @returns {Promise}
 */

const dapp = await Mobius.AppBuilder.build(APP_SECRET_SEED, USER_PUBLIC_KEY);
# Takes 2 Parameters
# App Secret Seed - string
# User Public Key - String
# Returns dapp instance

def dapp
  @dapp = Mobius::Client::App.new(dapp_secret_seed, user_public_key)
end
# Takes 2 Parameters
# App Secret Seed - string
# User Public Key - String
# Returns dapp instance

dapp = AppBuilder().build(app_secret_seed, user_public_key)
// Takes 2 parameters
// Param $APP_SECRET_SEED - App developer secret seed
// Param $USER_PUBLIC_KEY - User public key

$dapp = new Mobius\Client\App($APP_SECRET_SEED, $USER_PUBLIC_KEY);

Payment Methods##

Once the dapp has been initialized, payment methods can be called.

Charge###

Charges specified amount from user account and then optionally transfers it from app account to a third party in the same transaction.

/**
 * @param {number} amount - Payment amount
 * @param {?string} [target_address] - optional third party receiver address
 * @returns {Promise}
 */

const charge = await dapp.charge(amount, target_address);
# amount - number, Payment amount
# target_address - string, optional third party receiver address

def charge
  dapp.charge(amount, target_address)
end
# amount - number, Payment amount
# target_address - string, optional third party receiver address

charge = dapp.charge(amount, target_address)
// Param $amount - Payment amount
// Param $target_address - optional third party receiver address

$charge = $dapp->charge($amount, $target_address);

Transfer###

Sends money from the user account to the third party directly.

/**
 * @param {number} amount - Payment amount
 * @param {string} destination - third party receiver address
 * @returns {Promise}
 */

const transfer = await dapp.transfer(amount, destination);
# amount - number, Payment amount
# target_address - string, third party receiver address

def transfer
  dapp.transfer(amount, target_address)
end
# amount - number, Payment amount
# target_address - string, third party receiver address

transfer = dapp.transfer(amount, target_address)
// Param $amount - number, Payment amount
// Param $target_address - string, third party receiver address

$transfer = $dapp->transfer($amount, $target_address);

Payout###

Sends money from the DApp account to the user or third party.

/**
 * @param {number} amount - Payment amount
 * @param {string} [destination] - third party receiver address
 * @returns {Promise}
 */

const payout = await dapp.payout(amount, destination);
# amount - number, Payment amount
# target_address - string, third party receiver address

def payout
  dapp.payout(amount, target_address)
end
# amount - number, Payment amount
# target_address - string, third party receiver address

payout = dapp.payout(amount, target_address)
// Param $amount - number, Payment amount
// Param $target_address - string, third party receiver address

$payout = $dapp->payout($amount, $target_address);

Example##

The below example shows creating a Charge endpoint that would charge the user the requested amount and optionally transfer it from the DApp account to a third party in the same transaction.

//Using Express
app.post("/charge", async (req, res, next) => {
  try {
    const APP_SECRET_SEED = 'SD3XEDAPTGELU2L6XMX....KZEZRGJSPQNTXZRIC';
    const dapp = await Mobius.AppBuilder.build(APP_SECRET_SEED, req.user.sub);

    const { amount, target_address } = req.body;

    if (amount === null || isNaN(Number(amount))) {
      return res.status(400).json({ error: "Invalid amount" })
    }

    const response = await dapp.charge(amount, target_address);
    res.json({
      status: "ok",
      tx_hash: response.hash,
      balance: dapp.userBalance
    });
  } catch (e) {
    next(e);
  }
});
class AppController < ApplicationController
  skip_before_action :verify_authenticity_token, :only => [:pay] 
	
  ROUND_PRICE = 5
  
  # POST /charge
  def charge
    dapp.charge(ROUND_PRICE)
  rescue Mobius::Client::Error::InsufficientFunds
    render :gone
  end

  private

  def token_s
    session[:token] = params[:token] || session[:token]
  end

  def token
    @token ||= Mobius::Client::Auth::Jwt.new(Rails.application.secrets.app[:jwt_secret]).decode!(token_s)
  rescue Mobius::Client::Error
    nil # We treat all invalid tokens as missing
  end

  def dapp
    @dapp ||= token && Mobius::Client::App.new(
      # SA2VTRSZPZ5FIC.....I4QD7LBWUUIK
      Rails.application.secrets.app[:secret_seed], 
      token.public_key # Current user public key
    )
  end
end
@app.route('/api/charge', methods=['POST'])
@login_required
def charge(user_public_key):
  try:
    dapp = AppBuilder().build(app_secret_seed, user_public_key)

    try:
      data = json.loads(request.data.decode('utf-8'))
      amount = data['amount']
    except:
      amount = 1

      if not amount or not float(amount):
        return abort(400, description='Invalid amount')

      response = dapp.charge(amount)
      hash_meta = binascii.hexlify(response.hash_meta()).decode()

      return jsonify({
        'status': 'ok',
        'tx_hash': hash_meta,
        'balance': dapp.user_balance(),
      })
  except Exception as error:
    return error
if($endpoint == '/api/charge' && $_SERVER['REQUEST_METHOD'] == 'POST'){
  try{
    // decodes JWT and returns the users public key
    $public_key = getPublicKey($_GET['token']);

    if(isset($_REQUEST['amount'])){
    	$amount = $_REQUEST['amount'];
    }
    else{
    	$amount = 1;
    }

    $dapp = new Mobius\Client\App(APP_KEY, $public_key);
    $response = $dapp->charge($amount);

    echo json_encode( array(
        'status'    => 'ok',
        'tx_hash'   => $response->getRawData()['hash'],
        'balance' => $dapp->balance()
    	)
    );
  }catch(\Exception $e){
  	echo $e->getMessage();
  }
  die;
}

❗️

Using Environment Variables

Make sure you keep all your secret seeds stored safely, extracting into ENV variables or equivalent. Keys present throughout the documentation only serve for example purposes and belong to an account in the Test network.


What’s Next

Submit your DApp and test it on the Beta DApp Store