This is a placeholder for discussing the long-requested ability for a buyer to add a shipping address when making an offer. This hasn't been done yet because we obviously don't want to store unencrypted, sensitive information publicly. And the messaging infrastructure was not stable enough to rely on for this use.
Here's one potential way this can work:
Seller has a public key with which the Buyer's shipping address will be encrypted. This could be:
Before a Buyer makes an Offer, they encrypt their shipping address using one of the keys specified above as well as including an expiration date. This blob is sent to IPFS and the hash stored.
The Offer JSON is then created that includes the IPFS hash of the encrypted shipping address, as well as the expiration date. Once the item has been finalized or the expiration date has passed, the IPFS item for the shipping address is unpinned by the listener. This ensures that the buyers shipping information is deleted, even though it is encrypted. The expiration date serves as a backup... no one should be in possession of a file where the expiration date has passed.
Here are some pseudo-coded example IPFS objects for listing, offer and shippingDetails:
Listing
{
id: "1-000-123",
title: "Nick's Camera",
price: "1 Eth",
keys: [{
type: "PGP",
pubKey: "0x123ABC..."
}]
}
Offer
{
id: "1-000-123-1",
price: "1 Eth",
keys: [{
type: "PGP",
pubKey: "0x789DEF..."
}],
shippingData: {
ipfsHash: "Qm123...",
expires: "2019-04-19T06:01:17.171Z"
}
}
Shipping
{
type: "PGP",
expires: "2019-04-19T06:01:17.171Z",
data: "0xabc123..."
}
I would recommend also adding the requirement that any purchase over $100 requires signature verification. My wife works in the industry and sees fraud occur on a daily basis. Signature verification and tracking will eliminate most of these headaches.
Overall this would work nicely !
I'd vote for using the seller's ETH public key to encrypt the data, to keep things simpler for the seller (having to manage another key would confuse users imho).
Regarding deleting the data on IPFS, we can't really guarantee that. Even if the Origin community IPFS cluster unpins that data, it may still be on other IPFS clusters that we have no control of.
Regarding expiration date: if not for the purpose of deleting the data, l still agree it's worth storing a date with the address - could be useful to the seller later. Perhaps if the seller needs to replace the item or send some extra part later on, for checking that the address date is not too old and can still be used.
I'm not sure the Eth public key is an option as, in order to decrypt the message, we'd need access to the raw private key which isn't possible with most wallets (eg MetaMask). Instead we can just sign a pre-determined message and use that as the private key (like we do for messaging).
We can't guarantee data deletion but we can at least remove it from our own servers in order to be GDPR compliant. I see this as similar to deleting a Tweet... once deleted you can no longer retrieve it from Twitter's servers directly, but if someone else already has it from the API or a screenshot there's not much you can do about it.
Ah yes, good point regarding MetaMask not supporting decryption with Eth private key. Using similar technique as messaging makes sense, though I hate having yet another popup the user has to sign... but I can't think of a better alternative. At least with Origin Wallet we can make that transparent to the user.
Yes, makes sense regarding Origin cluster honoring the deletion of the address IPFS blob.
@nick I was talking to @matthewliu and @auregimon yesterday about a simpler, interim solution. We're currently encouraging buyers to send messages containing their addresses to sellers. Two of our three observed users yesterday wanted to have a structured form that would be likely to autocomplete. So how about just giving them an address form either inside the "next step box" or in the "new message modal". It could simply generate a message to send to the seller just as it would today. We're fairly certain that we don't want to present an address form prior to the makeOffer transaction, at least not until we decide to go deeper on a specific vertical where it's definitely critical to the sale. In future versions, it would be good to explore the idea of expiring or revoking access.
+1 for using our existing messaging system for shuttling these bits around.
I was talking yesterday with @wanderingstan about the messaging-based, post-offer, interim solution and came to the question of how we would know that a buyer had sent the address to the seller of an address-required listing.
First, at the risk of stating the obvious, it requires that messaging be enabled. But I think we're good with that since the shipping address "requirement" doesn't block anything at the contract level.
Second, I presume that we would add some metadata to a message when we send it. We could add a type to the message object (maybe 'shippingAddress') and include an offerId. Then we could check for whether the conversation between these two users contains a message of type shippingAddress and offerId equaling the one in question. In the old days, we used to add listingId and/or purchaseId to a message object if it was sent from a relevant page in the DApp (as opposed to from an existing conversation or a public user profile) - see also https://github.com/OriginProtocol/origin/issues/1837.
There's also a slightly different approach that one of our investors proposed. He wanted to set his address at the identity level so that he wouldn't have to input it every time. And ultimately, he would like the ability to see which people or services he had disclosed it to and be able to update it once across all of these or potentially revoke it selectively. We've talked in the past about adding an attestation for physical address (using something like Lob). That makes more sense for verifying a home sharing host, but could be connected to shipping address. Although it's not necessarily true that a buyer will always want to use the same one.
Hmm the interim solution is starting to sound complex. I think we could take a hybrid approach where we use existing messaging keys for encryption but store the actual data in IPFS. I think that'd be relatively simple to implement.
In addition to the listing creation side of this, here are some updated mockups for shipping address integration in the buying/selling process.
@DanielVF Here is the issue I was mentioning today with a proposal for handling shipping addresses...
Here are a few updated designs for the seller's side of this:
I now roughly understand the messaging-client, and have added success-path unit testing to it.
I've added two methods that allow us to use the normal messaging keys to encrypt messages that can then be passed along outside the normal conversations or messaging system.
await messaging.createOutOfBandMessage(address, contents)
await messaging.decryptOutOfBandMessage(m)
I'll be cleaning up the tests, and documenting this before moving on to the the Dapp UI and GraphQL layer.
Done and merged with #3241
Most helpful comment
Here's one potential way this can work:
Seller has a public key with which the Buyer's shipping address will be encrypted. This could be:
Before a Buyer makes an Offer, they encrypt their shipping address using one of the keys specified above as well as including an expiration date. This blob is sent to IPFS and the hash stored.
The Offer JSON is then created that includes the IPFS hash of the encrypted shipping address, as well as the expiration date. Once the item has been finalized or the expiration date has passed, the IPFS item for the shipping address is unpinned by the listener. This ensures that the buyers shipping information is deleted, even though it is encrypted. The expiration date serves as a backup... no one should be in possession of a file where the expiration date has passed.
Here are some pseudo-coded example IPFS objects for listing, offer and shippingDetails:
Listing
Offer
Shipping