issuance, trustline and paymentpath

Technical questions about the Ripple API, the protocol, etc.
Google [Bot] like(s) this thread.

issuance, trustline and paymentpath

Postby JFA » Fri Apr 21, 2017 3:55 pm

Hello
I want to port on the Ripple network a basic payment application initially developed on the Ethereum blockchain and using “ERC20” tokens called Lips (LP0 in the example)
Ripple seems perfectly suitable but I have some problems to understand issuance of tokens, trustline and payment paths.
I did not find tutorials with complete scenarios, only some (good but ) limited examples. Are there some tutorials outside of the beginner’s one?

Below is my scenario that I tried to simplify as much as possible with 3 valid and active accounts
Bank B 'rDc1pA1VoH46hnfq7zsdquJbWpMRqPGPWV',
Customer C 'rnT4dDw2CgsYBfTQhPHXB7q8j8Hphk6DuF'
Service Provider S ‘r9CtyXkbenXX3j2bxpDNX5sy9vfDZxfjn’

• bank B will issue LP0 tokens when Customer C makes a deposit in Euros
• Customer C can spend his/her tokens and buy some services to service provider S. C directly pays S
• Service Provider S gets Euros back from the bank B

C creates a trustline with a limit of 100 LP0 with B as counterparty and option ripplingDisabled: false
B makes a payment of 87 LP0 to C after C has made a deposit of 87Euros
When we check B and C trustlines it seems OK, even if I do not understand where counterparty.limit and counterparty. ripplingDisabled come from and mean.

C trustline
Code: Select all
[ { specification:
     { limit: '100',
       currency: 'LP0',
       counterparty: B},
    counterparty: { limit: '0', ripplingDisabled: true },
    state: { balance: '87' } }
]


B trustline
Code: Select all
[  { specification:
     { limit: '0',
       currency: 'LP0',
       counterparty: C,
       ripplingDisabled: true },
    counterparty: { limit: '100' },
    state: { balance: '-87' } } ]

Then I tried to make a 7 LP0 payment from Customer C to Service Provider S that failed
Code: Select all
{ resultCode: 'tecPATH_DRY',
  resultMessage: 'Path could not send partial amount.' }

Then I tried to create to create a trustline from S to C and restart the payment. It worked but creates a new line in the LP0 balance independent from first one. This is normal, but not what I expected. My goal is to get 7 Lips for the 87 Lips balance to make the payment
Below is C balance
Code: Select all
[
  {
    "currency": "XRP",
    "value": "20.986081"
  },
  {
    "currency": "LP0",
    "counterparty": "Bank",
    "value": "87"
  },
  {
    "currency": "LP0",
    "counterparty": "Service Provider",
    "value": "-7"
  }
]

What did I miss?
What should be the list of operations to make my scenario work?
Thanks for your help
JFA
 
Posts: 3
Joined: Tue Apr 11, 2017 12:07 pm

Re: issuance, trustline and paymentpath

Postby JoelKatz » Fri Apr 21, 2017 7:23 pm

Bank should set asfDefaultRipple on its account. Customer should disable rippling.

If the trust line was created before asfDefaultRipple was set, the Bank should enable rippling on the trust line to the customer. Issuers are rippling hubs, they must enable rippling by default or their users will be unable to ripple payments through them.

Here's a little background:

Rippling is when someone else's payment passes through you and shifts your asset or obligation to have a different counterparty.

Generally, ordinary users don't want rippling as it increases their risk of default.

But issuers must allow rippling. If Alice pays Bob with funds issued by Charlie, Alice's payment makes Charlie owe Alice less and Bob more. This is rippling. Charlie wants to allow this, it's what makes his asset useful.

A trust line always exists between two accounts. When a trust line is explicitly created (with a SetTrust transaction), the active side creates the trust line and the passive side doesn't perform any transaction. To protect users from exploits, by default, the passive side automatically sets no ripple on the trust line. Issuers don't want this and must set the "asfDefaultRipple" account flag to disable it.

See https://ripple.com/files/GB-2015-04.pdf
User avatar
JoelKatz
Ripple
Ripple
 
Posts: 1859
Joined: Sun Dec 23, 2012 3:45 pm
Location: Oakland, CA

Re: issuance, trustline and paymentpath

Postby JFA » Sat Apr 22, 2017 1:58 pm

Thanks a lot for your detailed answer. Things are now working as expected.

Below are my operation logs that can be useful for newcomers. some remaining questions are within italics

The bank account has enabled the asfDefaultRipple.
I didn’t find any ripple API to do it (is there an api to change the settings of an account? , but it was possible to change the defaultRipple through the Ripple wallet setting.

Customer C has created a trustline to the bank with default parameters
Code: Select all
const trusline = {
  "currency": "LP1",
  "counterparty": Bank,
  "limit": "100",
  ]
};


Service provider S has created a trustline to the bank with default parameters. I got some strange message that I was not able to interpret
Code: Select all
trusline transaction prepared...
Trustline transaction signed...
{ resultCode: 'terQUEUED',
  resultMessage: 'Held until escalated fee drops.' }


When I checked the trustline, it seems to be created. I executed the same operation a second time with the same result. Then a third time after having increased the XRP balance of the bank account that was below some "reserve". What is this reserve and why is it not constant? (25 XRP for the Bank account; 35XRP for the Service provider account?
The third time the trustline was declared successful, but I don't know if there is a relationship with the balance greater tha the reserve

Then I made the payment from Bank to Customer that worked
Then I tried a payment from Customer to Service Provider that failed
Code: Select all
Connected...
Payment transaction prepared...
Payment transaction signed...
{ resultCode: 'tecPATH_DRY',
  resultMessage: 'Path could not send partial amount.' }


To make it work, it was necessary to explicitly define the counterparty in the payment transaction
Code: Select all
const payment = {
  "source": {
      "address": Customer,
      "maxAmount": {
     "value": '2',
     "counterparty": Bank,   
     "currency": 'LP1'
      }
  },
    "destination": {
   "address": Service Provider,
   "amount": {
       "value": '2',
       "counterparty": Banl,      
       "currency": 'LP1'
   }
    }
};


Thanks again for your answer.
JFA
 
Posts: 3
Joined: Tue Apr 11, 2017 12:07 pm

Re: issuance, trustline and paymentpath

Postby JoelKatz » Mon Apr 24, 2017 5:24 pm

RCL requires the payment transaction to specify all the candidate paths that the transaction can use. At execution time, the "best" paths are used incrementally to execute the transaction.

We generally recommend that people use pathfinding because there may be unexpected combinations of paths that can make a payment cheaply. But if you know for a fact that the only asset you hold for the source currency and the only asset the recipient will accept for the source currency are the same asset, you can just specify the counterparty.
User avatar
JoelKatz
Ripple
Ripple
 
Posts: 1859
Joined: Sun Dec 23, 2012 3:45 pm
Location: Oakland, CA

Re: issuance, trustline and paymentpath

Postby JFA » Wed Apr 26, 2017 12:32 pm

Hello, thanks again for your detailed comments.
We are currently in the simple case where there is only one asset for the source and the recipient and we know a global counterparty for both of them. However we will expect to extend later the functionality of our application and I still miss something in understanding paths.
If I make a payment between customer C and Service Provider S with bank B as a counterparty, it works. If I run a getpath api to find candidate paths between C and S it returns an empty set. In fact this seems consistent with the behavior observed with Gatehub. When I try to send Lips from C to S, Gatehub does not find any path and does not allow to perform the transaction. I don’t know what I miss.

Code: Select all
const pathfind = {
  "source": {
    "address": Caddress
  },
  "destination": {
    "address": Saddress,
    "amount": {
   "currency": "LP1",
   "counterparty": Baddress,
   "value": "2"
    }
  }
};

const payment = {
  "source": {
      "address": Caddress,
      "maxAmount": {
     "value": '2',
     "counterparty": Baddress,   
     "currency": 'LP1'
      }
  },
    "destination": {
   "address": Saddress,
   "amount": {
       "value": '2',
       "counterparty": Baddress,      
       "currency": 'LP1'
   }
    }
};

function quit(message) {
  console.log(message);
  process.exit(0);
}

function fail(message) {
  console.error(message);
  process.exit(1);
}

api.connect().then(() => {
    console.log('Connected...');
    return api.getPaths(pathfind)}).then(paths => {
   console.log('paths...');
   console.log(paths);
    }).then(() => {
  return api.preparePayment(Caddress, payment, instructions).then(prepared => {
    console.log('Payment transaction prepared...');
    const {signedTransaction} = api.sign(prepared.txJSON, Csecret);
    console.log('Payment transaction signed...');
    api.submit(signedTransaction).then(quit, fail);
  });
   
}).catch(fail);


Code: Select all
Connected...
paths...
[ { source:
     { address: 'rnT4dDw2CgsYBfTQhPHXB7q8j8Hphk6DuF',
       maxAmount: [Object] },
    destination:
     { address: 'r9CtyXkbenXX3j2bxpDNX5sy9vfDZxfjn',
       amount: [Object] },
    paths: '[]' } ]
Payment transaction prepared...
Payment transaction signed...
{ resultCode: 'tesSUCCESS',
  resultMessage: 'The transaction was applied. Only final in a validated ledger.' }


I don’t know if this is the right place to report this kinf of problem, but I got an unexpected behavior in my integration environment
I developed these unit tests in a development environment which is a clone of Ripple github repository and everything works well.
In my integration environment, I installed Ripple-lib as recommended in the documentation though npm install ripple-lib and I got some strange messages when running the payment api:
$ref: all keywords used in schema at path "#". It will change in the next major version, see issue #260. Use option { extendRefs: true } to keep current behaviour

This has been already reported in a post on github https://github.com/ripple/ripple-lib/issues/736 and I had to re-install manually ajv module in version 4.0.5 and unfortunately also ripple-lib back to version 0.17.3 to temporarily bypass the problem.
JFA
 
Posts: 3
Joined: Tue Apr 11, 2017 12:07 pm


Return to Developers

Who is online

Users browsing this forum: No registered users and 6 guests