From eeff9af309eb138357e7fdc8e1b561c738250e25 Mon Sep 17 00:00:00 2001 From: Valeriy Gavrilin Date: Thu, 18 Apr 2019 15:11:02 +0300 Subject: [PATCH 1/6] WavesChat script --- ride4dapps/waveschat/README.md | 14 +++++ ride4dapps/waveschat/waveschat.ride | 83 ++++++++++++++++++++++++++ ride4dapps/waveschat/waveschat_test.js | 37 ++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 ride4dapps/waveschat/README.md create mode 100644 ride4dapps/waveschat/waveschat.ride create mode 100644 ride4dapps/waveschat/waveschat_test.js diff --git a/ride4dapps/waveschat/README.md b/ride4dapps/waveschat/README.md new file mode 100644 index 0000000..bc33a04 --- /dev/null +++ b/ride4dapps/waveschat/README.md @@ -0,0 +1,14 @@ +# WavesChat +WavesChat is a decentralized messenger with an end-to-end encryption +Basically works like a chat-roulette with an +1. Optional channel +2. Optional payment, which forces to pay the same amount to talk with you + +Try now at https://a51a0717-d701-40a6-afe6-6e09662ca8d0.pub.cloud.scaleway.com (Requires Waves Keeper **with InvokeScript support in TESTNET mode**) + +# How it works +1. First user (Bob) invokes script function `init(bobPublicKey)` +2. Second user (Alice) invokes `init(alicePublicKey)` +3. Script matches Bob's and Alice's public keys, so that they can get the recipients public key from data entry `Base58(Blake2b256(publicKey))` +4. Bob gets Alice's public key, encrypts message with it, and then invokes `sendMessage(bobPublicKey, cipherText)` +5. Bob to Alice conversation id is `Base58(Blake2b256(bobPublicKey + alicePublicKey))`, so Alice can get message count from `conversationId + "_n"` and messages from `conversationId + "_" + 0...msgCount` data entries accordingly, and decrypt it with her private key diff --git a/ride4dapps/waveschat/waveschat.ride b/ride4dapps/waveschat/waveschat.ride new file mode 100644 index 0000000..dc38f4d --- /dev/null +++ b/ride4dapps/waveschat/waveschat.ride @@ -0,0 +1,83 @@ +{-# STDLIB_VERSION 3 #-} +{-# CONTENT_TYPE DAPP #-} +{-# SCRIPT_TYPE ACCOUNT #-} + +let defaultAmount = 0 +let maxAmount = 5_0000_0000 + +@Callable(invoke) +func init(publicKey: ByteVector, channel: String) = { + let publicKeyHash = toBase58String(blake2b256(publicKey)) + let channelId = toBase58String(blake2b256(toBytes(channel))) + let currentKey = "current_" + channelId + let currentAmountKey = "current_amount_" + channelId + let isPublicChannel = size(channel) < 6 + + let pmtAmount = match invoke.payment { + case pmt:AttachedPayment => + if (isDefined(pmt.assetId)) then 0 + else pmt.amount + case _ => + 0 + } + + let requiredAmount = match getInteger(this, currentAmountKey) { + case currentAmount: Int => currentAmount + case _ => 0 + } + + let newRequiredAmount = if (isPublicChannel && pmtAmount >= maxAmount) then maxAmount else pmtAmount + + if (pmtAmount < requiredAmount) + then throw("Init requires " + toString(requiredAmount / 100000000) + " waves") + else { + match getBinary(this, publicKeyHash + "_owner") { + case b: ByteVector => + if (b != invoke.caller.bytes) then throw("Public key is not yours") + else { + match getBinary(this, currentKey) { + case left:ByteVector => + let leftHash = toBase58String(blake2b256(left)) + WriteSet([DataEntry(publicKeyHash + "_owner", invoke.caller.bytes), DataEntry(leftHash, publicKey), DataEntry(publicKeyHash, left), DataEntry(currentKey, 0), DataEntry(currentAmountKey, defaultAmount)]) + + case _ => + WriteSet([DataEntry(publicKeyHash + "_owner", invoke.caller.bytes), DataEntry(currentKey, publicKey), DataEntry(currentAmountKey, newRequiredAmount)]) + } + } + + case _ => + match getBinary(this, currentKey) { + case left:ByteVector => + let leftHash = toBase58String(blake2b256(left)) + WriteSet([DataEntry(publicKeyHash + "_owner", invoke.caller.bytes), DataEntry(leftHash, publicKey), DataEntry(publicKeyHash, left), DataEntry(currentKey, 0), DataEntry(currentAmountKey, defaultAmount)]) + + case _ => + WriteSet([DataEntry(publicKeyHash + "_owner", invoke.caller.bytes), DataEntry(currentKey, publicKey), DataEntry(currentAmountKey, newRequiredAmount)]) + } + } + } +} + +@Callable(invoke) +func sendMessage(publicKey: ByteVector, message: ByteVector) = { + let publicKeyHash = toBase58String(blake2b256(publicKey)) + + match getBinary(this, publicKeyHash + "_owner") { + case assignedCaller: ByteVector => + if (assignedCaller != invoke.caller.bytes) then throw("Public keys not match") + else match getBinary(this, publicKeyHash) { + case right: ByteVector => + let conversationId = toBase58String(blake2b256(publicKey + right)) + let nonceKey = conversationId + "_n" + let nonce = match getInteger(this, nonceKey) { + case i: Int => i + 1 + case _ => 1 + } + WriteSet([DataEntry(conversationId + "_" + toString(nonce), message), DataEntry(nonceKey, nonce)]) + + case _ => throw("Not initialized") + } + + case _ => throw("Owner not defined") + } +} diff --git a/ride4dapps/waveschat/waveschat_test.js b/ride4dapps/waveschat/waveschat_test.js new file mode 100644 index 0000000..ce2fdf1 --- /dev/null +++ b/ride4dapps/waveschat/waveschat_test.js @@ -0,0 +1,37 @@ +describe('Messenger test', () => { + const dappAddress = "3Musn2zFuw3G71yg6G7PDRAq7CjWxK7Z4pk" + + const firstPK = "FxKjemCJ9s9yrG5RuDXAtGXZNsTsAr1FMhzNmUKG4GyE" + const secondPK = "5nRF8WDnjWrGhZeYEV8zh7MG1kgpYbnJaEt5G3vsR4e2" + + const firstPKHash = "4CfQDi9nwsps25XA9yrMAw4XWFaG5NwLf6gFVjrTSGL7" + + it('Register for a chat', async function(){ + const tx = invokeScript({ fee: 500000, dappAddress: dappAddress, call:{function:"init",args:[{"type": "binary", "value": firstPK}, {"type": "string", "value": "test"}]}, + payment: [{amount: 1000000, assetId: null}]}) + const tx1 = invokeScript({ fee: 500000, dappAddress: dappAddress, call:{function:"init",args:[{"type": "binary", "value": secondPK}, {"type": "string", "value": "test"}]}, + payment: [{amount: 1000000, assetId: null}]}) + + await broadcast(tx) + await broadcast(tx1) + await waitForTx(tx1.id) + + await addressDataByKey(dappAddress, firstPKHash) + .then(result => chai.expect(result).to.equal(secondPK)) + }) + + it('Send message', async function(){ + const tx = invokeScript({ fee: 500000, dappAddress: dappAddress, call:{function:"sendMessage",args:[{"type": "binary", "value": firstPK}, {"type": "binary", "value": "4CfQDi9nwsps25XA9yrMAw4XWFaG5NwLf6gFVjrTSGL7"}]}, + payment: [{amount: 1000000, assetId: null}]}) + + await broadcast(tx) + await waitForTx(tx.id) + + const conversationId = "Bw864nv4WkYURMK1V75FjizKEfMy7f7YsoZ1JVkBYmRS" + await addressDataByKey(ballAddress, conversationId + "_n") + .then(result => chai.expect(result).to.equal(1)) + + await addressDataByKey(ballAddress, conversationId + "_1") + .then(result => chai.expect(result).to.equal(firstPKHash)) + }) +}) From c2515534448f5d95b4b9ace25b248e2d34551991 Mon Sep 17 00:00:00 2001 From: Le Karasique Date: Thu, 18 Apr 2019 15:29:42 +0300 Subject: [PATCH 2/6] Update waveschat_test.js --- ride4dapps/waveschat/waveschat_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ride4dapps/waveschat/waveschat_test.js b/ride4dapps/waveschat/waveschat_test.js index ce2fdf1..1b7f563 100644 --- a/ride4dapps/waveschat/waveschat_test.js +++ b/ride4dapps/waveschat/waveschat_test.js @@ -1,5 +1,5 @@ describe('Messenger test', () => { - const dappAddress = "3Musn2zFuw3G71yg6G7PDRAq7CjWxK7Z4pk" + const dappAddress = "3N7H98TgE5umm7vxwkdsLMVsny1icuu93Zh" const firstPK = "FxKjemCJ9s9yrG5RuDXAtGXZNsTsAr1FMhzNmUKG4GyE" const secondPK = "5nRF8WDnjWrGhZeYEV8zh7MG1kgpYbnJaEt5G3vsR4e2" From 40aaa7afa2077589b2e72ddf7a0f478b65de3a13 Mon Sep 17 00:00:00 2001 From: Le Karasique Date: Wed, 24 Apr 2019 13:45:18 +0300 Subject: [PATCH 3/6] Update README.md --- ride4dapps/waveschat/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ride4dapps/waveschat/README.md b/ride4dapps/waveschat/README.md index bc33a04..23d44e1 100644 --- a/ride4dapps/waveschat/README.md +++ b/ride4dapps/waveschat/README.md @@ -4,7 +4,7 @@ Basically works like a chat-roulette with an 1. Optional channel 2. Optional payment, which forces to pay the same amount to talk with you -Try now at https://a51a0717-d701-40a6-afe6-6e09662ca8d0.pub.cloud.scaleway.com (Requires Waves Keeper **with InvokeScript support in TESTNET mode**) +Try now at https://c77c579e-6dde-4971-92e7-e0439c25ccd0.pub.cloud.scaleway.com (Requires Waves Keeper **with InvokeScript support in TESTNET mode**) # How it works 1. First user (Bob) invokes script function `init(bobPublicKey)` From 11aaf27b5a0af8c38e44d93d5ffdb838eac18f10 Mon Sep 17 00:00:00 2001 From: Le Karasique Date: Wed, 5 Jun 2019 18:40:26 +0300 Subject: [PATCH 4/6] Update waveschat_test.js --- ride4dapps/waveschat/waveschat_test.js | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/ride4dapps/waveschat/waveschat_test.js b/ride4dapps/waveschat/waveschat_test.js index 1b7f563..3ab2eaa 100644 --- a/ride4dapps/waveschat/waveschat_test.js +++ b/ride4dapps/waveschat/waveschat_test.js @@ -1,5 +1,5 @@ describe('Messenger test', () => { - const dappAddress = "3N7H98TgE5umm7vxwkdsLMVsny1icuu93Zh" + const dappAddress = "3MwmaLMtWTaTyjhzywLLRQa4BH1PYZdvpKy" const firstPK = "FxKjemCJ9s9yrG5RuDXAtGXZNsTsAr1FMhzNmUKG4GyE" const secondPK = "5nRF8WDnjWrGhZeYEV8zh7MG1kgpYbnJaEt5G3vsR4e2" @@ -7,31 +7,21 @@ describe('Messenger test', () => { const firstPKHash = "4CfQDi9nwsps25XA9yrMAw4XWFaG5NwLf6gFVjrTSGL7" it('Register for a chat', async function(){ - const tx = invokeScript({ fee: 500000, dappAddress: dappAddress, call:{function:"init",args:[{"type": "binary", "value": firstPK}, {"type": "string", "value": "test"}]}, + const tx = invokeScript({ fee: 900000, dApp: dappAddress, call:{function:"init",args:[{"type": "binary", "value": firstPK}, {"type": "string", "value": "test"}]}, payment: [{amount: 1000000, assetId: null}]}) - const tx1 = invokeScript({ fee: 500000, dappAddress: dappAddress, call:{function:"init",args:[{"type": "binary", "value": secondPK}, {"type": "string", "value": "test"}]}, + const tx1 = invokeScript({ fee: 900000, dApp: dappAddress, call:{function:"init",args:[{"type": "binary", "value": secondPK}, {"type": "string", "value": "test"}]}, payment: [{amount: 1000000, assetId: null}]}) await broadcast(tx) await broadcast(tx1) await waitForTx(tx1.id) - - await addressDataByKey(dappAddress, firstPKHash) - .then(result => chai.expect(result).to.equal(secondPK)) }) it('Send message', async function(){ - const tx = invokeScript({ fee: 500000, dappAddress: dappAddress, call:{function:"sendMessage",args:[{"type": "binary", "value": firstPK}, {"type": "binary", "value": "4CfQDi9nwsps25XA9yrMAw4XWFaG5NwLf6gFVjrTSGL7"}]}, + const tx = invokeScript({ fee: 900000, dApp: dappAddress, call:{function:"sendMessage",args:[{"type": "binary", "value": firstPK}, {"type": "binary", "value": "4CfQDi9nwsps25XA9yrMAw4XWFaG5NwLf6gFVjrTSGL7"}]}, payment: [{amount: 1000000, assetId: null}]}) await broadcast(tx) await waitForTx(tx.id) - - const conversationId = "Bw864nv4WkYURMK1V75FjizKEfMy7f7YsoZ1JVkBYmRS" - await addressDataByKey(ballAddress, conversationId + "_n") - .then(result => chai.expect(result).to.equal(1)) - - await addressDataByKey(ballAddress, conversationId + "_1") - .then(result => chai.expect(result).to.equal(firstPKHash)) }) }) From e838bae0940a3c97064c4f9ee5363132c7a98cdd Mon Sep 17 00:00:00 2001 From: Le Karasique Date: Tue, 25 Jun 2019 17:34:34 +0300 Subject: [PATCH 5/6] Update waveschat_test.js --- ride4dapps/waveschat/waveschat_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ride4dapps/waveschat/waveschat_test.js b/ride4dapps/waveschat/waveschat_test.js index 3ab2eaa..5cfe25b 100644 --- a/ride4dapps/waveschat/waveschat_test.js +++ b/ride4dapps/waveschat/waveschat_test.js @@ -1,5 +1,5 @@ describe('Messenger test', () => { - const dappAddress = "3MwmaLMtWTaTyjhzywLLRQa4BH1PYZdvpKy" + const dappAddress = "3N3st6Cp9ZLz8kmT33EY41AVjwKqBVebvyq" const firstPK = "FxKjemCJ9s9yrG5RuDXAtGXZNsTsAr1FMhzNmUKG4GyE" const secondPK = "5nRF8WDnjWrGhZeYEV8zh7MG1kgpYbnJaEt5G3vsR4e2" From 11cc7ebc4d7520c208ab8a7d1ff127d1336fc178 Mon Sep 17 00:00:00 2001 From: Le Karasique Date: Wed, 26 Jun 2019 14:02:35 +0300 Subject: [PATCH 6/6] Update README.md --- ride4dapps/waveschat/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ride4dapps/waveschat/README.md b/ride4dapps/waveschat/README.md index 23d44e1..7b88489 100644 --- a/ride4dapps/waveschat/README.md +++ b/ride4dapps/waveschat/README.md @@ -4,7 +4,7 @@ Basically works like a chat-roulette with an 1. Optional channel 2. Optional payment, which forces to pay the same amount to talk with you -Try now at https://c77c579e-6dde-4971-92e7-e0439c25ccd0.pub.cloud.scaleway.com (Requires Waves Keeper **with InvokeScript support in TESTNET mode**) +Try now at https://chat.waves.today (Requires Waves Keeper **with InvokeScript support in TESTNET mode**) # How it works 1. First user (Bob) invokes script function `init(bobPublicKey)`