stellar / stellar-protocol

Developer discussion about possible changes to the protocol.
525 stars 303 forks source link

A proper URI protocol for Stellar #11

Closed johansten closed 6 years ago

johansten commented 10 years ago

https://github.com/pollen23/stellar-uri

roosmaa commented 10 years ago

+1

It would be really nice to have, especially the trust line creation part. It would make the gateway trusting kind of like authorising a Facebook app - painelss and quick, and the wallet could actually explain the what it means to trust a gateway (in words that the user would understand).

Maybe a return URI would also be beneficial? Ie when the client app has completed the requested operation it directs the user back to a given URL/mobile app instead of remaining open and leaving the user hanging. That way the gateway/merchant who requested the transaction can either show a thank you message or let the user try again if the user cancelled the payment.

nullstyle commented 8 years ago

@johansten I'd love to see this proposal updated for the new stellar network.

zulucrypto commented 7 years ago

From a slack discussion on URLs and QR code support, I think it would be helpful to gather use cases for things that a stellar protocol should be able to do.

I think having specific examples to reference would make it much easier to evaluate various proposals since you could give an example URI referencing the use case.

Here are some to get started:

Payment request A user should be able to click a URL and be prompted to pay an amount to an address

Import keys A user should be able to add a key or account to a wallet

Import contacts A user should be able to add an address (along with a human-friendly label) to the list of contacts in their wallet

Signing request A user should be able to sign a message with their private key and make the signature available to a callback URL

Add trust line Request that a user add a trustline for an asset and then call a callback URL

smdwireless commented 7 years ago

So the priority for this protocol is efficiency and its target is a machine not a human being. With that in mind, I think we should dial the priority of human readability down a notch and focus on making this an efficient protocol optimized for machine use and should be easily encodable into (and more importantly, reliably useable in) QR format.

Building on the work done by @sacarlson and @johansten I propose the following as a first concept draft open for review. It addresses the first two use cases outlined above by @zulucrypto and we can work on the others once we make some progress with this.

Proposed Stellar.org URI/QR code formats:

SIMPLE PAYMENTS REQUEST: stellar://spmt:{d:DESTINATION_ACCOUNT_ID,n:NETWORK_CODE,a:AMOUNT,s:{c:ASSET_CODE,i:ASSET_ISSUER},m:{t:MEMO_TYPE,x:MEMO},q:FEDERATION_DOMAIN,v:VERSION} Example QRCODE for simple payments request

ESCROW PAYMENTS REQUEST: stellar://epmt:{d:DESTINATION_ACCOUNT_ID,n:NETWORK_CODE,a:AMOUNT,s:{c:ASSET_CODE,i:ASSET_ISSUER},m:{t:MEMO_TYPE,x:MEMO},q:FEDERATION_DOMAIN,u:ORDER_STATUS,b:{z:THIRD_PARTY_ACCOUNT_ID,w:EMAIL_ADDRESS,y:EXPIRY TIMESTAMP,g:STATUS_MESSAGES,f:FEE,l:WEBHOOK_URL},j:PROTOCOL,v:VERSION} Example QRCODE for escrow payments request

CONTACT: stellar://acct:{i:ACCOUNT_ID,n:NETWORK_CODE,e:SURNAME;FIRSTNAME;OTHER_NAME0;OTHER_NAME1,o:COMPANY_NAME,p:WORK_TEL;MOBILE_TEL,l:WEBHOOK_URL,w:EMAIL_ADDRESS,h:DELIMITED_ADDRESS_FIELDS,j:PROTOCOL,v:VERSION} EXAMPLE QRCODE for contact

CHALLENGE/RESPONSE: stellar://chlg:{i:ACCOUNT_ID,m:MESSAGE,l:WEBHOOK_URL,v:VERSION} EXAMPLE QRCODE for Challenge Response

ACCOUNT EXPORT/IMPORT: stellar://xprt:{n:NETWORK_CODE,k:SEED,v:VERSION} stellar://xprt:{n:NETWORK_CODE,r:ENCRYPTEDSEED,v:VERSION} EXAMPLE QRCODE for Account Export|Import

Key for the above format:

VERSION*: Protocol version number (single case-sensitive character [0-9a-zA-Z])

DESTINATION_ACCOUNT_ID* = self explanatory

NETWORK_CODE = Network is only needed if not stellar.org live network otherwise 'N'. It is the first eight hex characters of the SHA-256 hash of the network passphrase, function getHash(passphrase) { return new StellarSdk.Network(passphrase).networkId().toString('hex').slice(0, 8); }

    Examples:
        Live net - "7ac33997"
        Test net - "cee0302d"

AMOUNT* = self explanatory

ASSET_CODE* = Asset is only needed if not XLM otherwise 'N'

ASSET_ISSUER = this would be the trustline ID if it is needed

MEMO_TYPE = N/T/I/H/R (None/Text/ID/Hash/Return Hash)

MEMO = self explanatory

FEDERATION_DOMAIN: optional federation server domain name if it exists (eg domain.tld)

ORDER_STATUS: This will be what state the store sees this tx_tag order in, 'N' means it does not yet exist. when already paid this becomes a value of 0 - X indicating that the order has already been paid or had an error and prevents the wallet from allowing to pay more than 1 time.

THIRD_PARTY_ACCOUNT_ID: This is the 3rd party escrow agents publicID that becomes a signer in the escrow contract

EXPIRY TIMESTAMP: 1490574272 // timestamp of expire time when the store can recover it's funds with no reponse from the buyer.

STATUS_MESSAGE: Special status message state information of the excrow contract

FEE: This is the escrow service fee in XLM that is sent to the 3rd party escrow agent, this fee is optional depending on what the 3rd party wants to charge.

PROTOCOL: This is the escrow protocol version in use or in the context of CONTACT it the last revision (vcard REV), date of last update (YYYYMMDDTHHMMSSZ eg: 20171104T193000Z)

EMAIL_ADDRESS: self explanatory in the contact context/the email contact info for the 3rd party escrow agent in the payments request context

ACCOUNT_ID* = Stellar account Public Key of the contact

SURNAME: self explanatory

FIRSTNAME: self explanatory

OTHER_NAME0: Could be online handle/nickname or middle name

OTHER_NAME1: Could be online handle/nickname or middle name

COMPANY_NAME: self explanatory

AREA_CODE: Full PSTN countrycode or area code (eg: +44 or +1604 etc)

WORK_TEL: Full international PSTN local telephone number (eg: +442031234567 or +16043334444 etc)

MOBILE_TEL: local mobile number (eg: +447771234567 or +16043334444 etc)

DELIMITED_ADDRESS_FIELDS: Address delimited by ';' (content fields are in order: Post Office Address; Extended Address; Street; Locality; Region; Postal Code; Country)

MESSAGE*: Challenge response message

WEBHOOK_URL: Callback URL in the context of challenge/response, company or personal website in the context of the contact information and callback URL that the wallet will submit the escrow transaction package to after the customer confirms payment from the wallet in the context of payments request.

SEED: Standard account private key

ENCRYPTEDSEED: Encrypted account private key

*: Mandatory fields. All non-mandatory key values must be represented by 'N' if not in use

-hatter

zulucrypto commented 7 years ago

I think we should separate the discussion of URIs and QR codes since URIs have many more uses than just QR codes. QR codes could also be optimized once we have a URI format or in some cases could just point a generic QR code reader to a website that forwards to a stellar:// URI, which would then be opened by a protocol handler on their device (aka a Stellar Wallet).

Regarding the URI format, I think we should avoid mixing JSON into the URI. That makes it necessary to do two kinds of encoding/escaping when I think standard URI libraries would already support what we need and exist for every platform.

Here's how I'd propose changing one of your examples to use a purely URI approach:

SIMPLE PAYMENTS REQUEST: stellar://v1/payment?d=DESTINATION_ACCOUNT&n=NETWORK_CODE&a=AMOUNT&c=ASSET_CODE&i=ASSET_ISSUER&mt=MEMO_TYPE&m=MEMO&Q=FEDERATION_DOMAIN

Some reasons I like sticking with a URI-style format:

  1. Only one kind of parsing/escaping to worry about
  2. Still machine readable
  3. Fewer bytes than your JSON example (135 vs. 151)
  4. No nested fields (memo and asset in your example)

The only thing I've heard everyone agree on is that the protocol should start with stellar:// , so let's take that as our first part of the standard. :)

Ignoring QR codes for now (I think they should be a separate discussion/standard), let's see if we can get agreement on:

Should the stellar:// protocol use a plain URI format or encode fields with JSON?

smdwireless commented 7 years ago

@zulucrypto I have no problem with plain url format but if we needed to use the same variable type twice to refer to the variable for two different users, eg in a multi-signature environment, the nesting helps keep things cleanly separated.

Might I suggest using a hybrid with nesting as necessary. Just a thought.

-hatter

antb123 commented 7 years ago

@zulucrypto can you outline how this will work with federation forward?

e.g.:

https://YOUR_FEDERATION_SERVER/federation?type=forward&forward_type=bank_account&swift=BOPBPHMM&acct=2382376

zulucrypto commented 7 years ago

@smdwireless That's a great point and probably the biggest weakness of staying with URIs.

Although there's no standard way to encode an array in a URI the two methods I've seen are:

  1. Use [] notation: ?signer[]=G123&signer[]=G234 (supported by PHP, Rails, and Angular)
  2. Pass the field multiple times: ?signer=G123&sigher=G234 (supported by Angular)

Since (to the best of my knowledge) 1 is the most widely supported, I'd vote for that.

Example request to add two contacts in a single url

stellar://v1/add-contact?address[]=G123&label[]=Poloniex&address[]=G456&label[]=Bittrex

The protocol handler would parse the arrays in the order they appeared in the URI and then match up addresses and labels by index:

$addresses = ['G123', 'G456'];
$labels = ['Poloniex', 'Bittrex'];

// Therefore, 'Poloniex' has address 'G123'

Looks like this is the next thing to decide (if we go with URIs): How should multiple values for a single field be encoded?

smdwireless commented 7 years ago

@tempofr you have raised a valid point... using a plain url method would lead to collisions and ambiguities in the decoding of the data. It doesn't lend well to having urls as variables either, you will need to urlencode them which brings us right back to the issue of saving characters.

-hatter

smdwireless commented 7 years ago

@zulucrypto

Looks like this is the next thing to decide (if we go with URIs): How should multiple values for a single field be encoded?

Honestly it seems it will be back to key=>value pair nesting... ie: JSON notation

Otherwise the number of times you'll have to parse to get your data out will make for much more resource intensive operations than simply using the built-in JSON interpreter.

-hatter

zulucrypto commented 7 years ago

@tempofr I believe in that case you could URL-encode the parameters and pass them as a forward parameter in the stellar:// protocol URL.

For your example above:

  1. Url encode the forwarding portion. forward_type=bank_account&swift=BOPBPHMM&acct=2382376 becomes forward_type%3Dbank_account%26swift%3DBOPBPHMM%26acct%3D2382376

  2. Include this in a payment request:

// URL format:
stellar://v1/payment?d=zulucrypto*tempo.fr&forward=<url encoded data from #1>

// Final URL:
stellar://v1/payment?d=zulucrypto*tempo.fr&forward=forward_type%3Dbank_account%26swift%3DBOPBPHMM%26acct%3D2382376

When I clicked on the above URL the wallet application would see that the destination was not a stellar address and it would do a federation lookup:

  1. Wallet requests stellar.toml for tempo.fr
  2. Wallet parses FEDERATION_SERVER from stellar.toml
  3. Wallet makes a request to FEDERATION_SERVER an adds the (decoded) forward parameter from the stellar:// url.

The final URL requested by the wallet ends up being https://FEDERATION_SERVER/federation?type=forward&forward_type=bank_account&swift=BOPBPHMM&acct=2382376

zulucrypto commented 7 years ago

@smdwireless Could you look at my comment to tempofr RE: forwarding and see if that would work? If not, could you provide an example where there would be a collision or ambiguity?

smdwireless commented 7 years ago

@zulucrypto I will run some scenarios and come back with results either way. Hopefully this can work.

-hatter

smdwireless commented 7 years ago

@zulucrypto other than the increased character count from using the encoding, it seems to work just fine. I'm just not sure how much is saved by not using JSON notation... it seems this makes for a longer URI.

-hatter

zulucrypto commented 7 years ago

@smdwireless Great, thanks for looking into it.

I'll start work on defining and supporting some exact URLs as part of working on my browser extension (https://galactictalk.org/d/505-comments-requested-secure-browser-extension/6).

I'd appreciate any other use cases people could add since they'd help me come up with a good API for the extension.

bartekn commented 6 years ago

Everyone interested see discussion going on here: https://github.com/stellar/stellar-protocol/pull/95

jedmccaleb commented 6 years ago

SEP7: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0007.md