Reddit NEM Tipbot


#1

Users are finding new ways to use their XEM everday, in order to further support that sentiment the NEM Tipbot for Reddit has been created.

What is the NEM Tipbot for Reddit?

The NEM Tipbot for Reddit allows users to tip other users in XEM directly through Reddit. This is similar to other existing crypto currency bots, however, we take advantage of features inherit to the NEM block-chain (such as encrypted messages) to give users more explicit control over their tipping funds.

How to use the bot

Registering is easy, simply send a message to /u/nemtipbot with a subject of register

You will receive a response from the bot similar to the one pictured below:

follow the instructions provided in the message.

Once the bot has received your transaction with the challenge code, it will then generate a NEM wallet associated to your Reddit user and send you an encrypted transaction containing the private key of your account.

In the Nano Wallet you can Decode the message, and obtain the private key. You can then import it into the Nano Wallet allowing you complete control over the funds in your tip account.

You will also receive a follow up private message on reddit confirming your transaction has been received and your account created. The reddit message will also include the address to your new account so that you may begin funding it immediately.

Tipping

To tip a user, simply respond to a comment of a user you want to tip using the !tipxem command and an amount. For example, to send 100 XEM to a user simply respond with a comment beginning with !tipxem 100. The bot will automatically transfer funds from your tip account to the other user’s tip account.

Example of tipping:

If the receiving user does not already have a tip account, the bot will automatically generate a wallet for that user. Once the receiving user registers with the bot, they will be able to access their funds.

In this way, the NEM Tipbot for Reddit differs from most other tipping bots as it does not utilize a shared hot wallet, instead each user has a seperate account in which they have complete control over. In the case of catastrophic data failure (bot’s database exploding) users will still have complete access to their funds as the private key to their account is encrypted and stored on the blockchain.

Future Plans

Future plans to extend the bot include adding support for registering multi-sig accounts – adding another layer of security and further empowering users control of their funds. We also plan to add support for tipping in mosaics as-well.

Development

The source-code for the NEM Tipbot for Reddit is available on GitHub. We encourage users to file bug reports and pull-requests.

We will make a follow-up blog post outlining the technical details of the bot. Stay tuned!

Testing

The tipping bot will begin testing on the Testnet starting June 26th 2017 on the NEM subreddit. Please contact @daifukunem on Telegram if you’d like to assist in the testing process. The bot will run on the Mainnet once it has been thoroughly tested.


NEM’s Prototype Project Bounty Program
#2

reserved


#3

great work, hopefully the new fee structure will be in place as well once it goes live!


#4

very nice! sign me up as a volunteer. I’d really like to see how practical it is with fee’s as mentioned.


#5

Yes, right now it costs 6 XEM just to register which is unfortunately pretty pricey. This is one reason I’m holding off on multisig support too since those fees are even higher.


#6

Will do. I plan to create a test thread on the NEM sub-reddit and everyone can participate in there. I set a date mainly because I wanted to give people a chance to acquire XEM on the Testnet. If you need XEM on Testnet please message me your Testnet address on telegram (username is @daifukunem) and I’ll send some over.


#7

hi, great job. i came across two/three issues though.

the first is that i got sent the message that should have been sent to the user i tipped stating “you have not been registered, register to collect etc”

and the other, i imported the private key that was sent to me. it contained xem that i got tipped, but it doesnt contain the xem i deposited (which i sort of expected)
and then, if you tip fractional amounts, there is a loss of precision of 6 decimals. ie. send a tip of 1.123456 xem, and only 1.0 gets sent, meaning the fractional amount is being kept by the bot. not sure if thats by design or not but i can imagine people might complain about that.

over all great job though!


#8

Replace the decimal . with a comma and it should work , This looks like a bug, but might be a feature. Happened on one of the other tools, paycontent.


#9

Hey kodtycoon, I really appreciate the feedback and I’ll get those issues sorta asap.

I did want some clarification on a couple of the issues you reported.

Yes, the message replies to the person who did the tip, i.e. if you do !tipxem 100, the bot will reply to that comment and highlight the user who was tipped. I believe this is how most tip bots currently handle it, however if there’s a different way I should handle it I’m welcome to suggestions :smile:

When you say deposited, do you mean you sent it to the address of that private key? What user was this private key registered under? The bot doesn’t have any sort of internal tracking of amounts or a shared wallet, it’s intentionally dumb in that sense. The tip transactions simply leverage the tip account (NEM private key you were sent) and directly construct transfer transactions from those accounts and post them to the network.

Nice catch! I’ll get that sorted :smile:

Thanks!


#10

no problem :slight_smile: yeah i think what happened is i saw the notification in my mail and assumed it was a private message lol (i dont use reddit all that much really).

i just deposited to the address sent to me in private mail. i dont think it is the address that was sent via encrypted message. its strange because i deposited 9k to the deposit account provided, successfully tipped people and received some back, and when i imported the account, there was only 38 in it. i will dig a little deeper in a bit though and forward address/keys if its still not there.

ok cool :slight_smile: i tried negative numbers and such too and it seemed the only thing that tripped it up was the decimals. :wink:


#11

Hey, @kodtycoon I’m in the process of implementing multi-sig support right now, I addressed most of the issues you’ve mentioned above in the dev branch already but I won’t have another test run ready for a few days.

Once I’m done with the implementation and testing I will need to re-write the blog post for multi-sig.


#12

Users are finding new ways to user the XEM everyday, in order to further support the sentiment the NEM Tipbot for Reddit has been created.

What is the NEM Tipbot for Reddit?

The NEM Tipbot for Reddit allows users to tip other users in XEM directly through Reddit. This is similar to existing crypto currency bots, however, we take advantage of features inherit to the NEM block-chain. In fact, this tip bot is the first trustless cryptocurrency tip bot.

Security

The NEM Tipbot uses 2-of-3 multi-sig to give users more security and explicit control over their tipping funds. What does this mean? In short, all tipping transactions made by the bot on behalf of another user must be cleared by that user. Furthermore, the user controls 2 out of the 3 cosigner accounts, which gives the user complete control over the account. If the bot’s database were to be compromised the attacker would not be able to steal XEM from any multi-sig accounts.

The only case where an account is not multi-sig is when a receiving user’s Reddit account has not been registered with the bot. i.e. Alice tips Bob on Reddit but Bob has not registered his account with the tip-bot yet. In this case, the bot automatically generates a new account for Bob and begins the multi-sig transaction on behalf of Alice. Once Alice signs the transaction via the Nano Wallet, XEM will be transfered from Alice’s multi-sig account to Bob’s account on the blockchain. At this point, however, Bob’s account is not a multi-sig account. Bob’s tip account will be converted to a multi-sig account once he registers with the bot.

Realistically though, most users will want to register promptly to claim their XEM.

How to use the bot

Registering is easy, simply send a message to /u/nemtipbot with a subject or body of register.

You will receive a response from the bot similar to the one pictured below:

follow the instructions provided in the message.

Once the bot has received your transaction with the challenge code, it will generate a multi-sig account and send you an encrypted transaction containing the private key of the account. You’re not required to do anything with this transaction, but you are free to import the private key into Nano Wallet.

You will also receive a follow up private message on reddit confirming your transaction has been received and your account created. The reddit message will also include the address to your new account so that you may begin funding it immediately.

Successfully Registered

Tipping

To tip a user, simply respond to a comment of a user you want to tip using the !tipxem command and an amount. For example, to send 100 XEM to a user simply respond with a comment beginning with !tipxem 100. The bot will automatically transfer funds from your tip account to the other user’s tip account.

Example of tipping:
Tip Example

If the receiving user does not already have a tip account, the bot will automatically generate a wallet for that user. Once the receiving user registers with the bot, they will be able to access their funds.

In this way, the NEM Tipbot for Reddit differs from most other tipping bots as it does not utilize a shared hot wallet, instead each user has a seperate account in which they have complete control over. In the case of catastrophic data failure (bot’s database exploding) users will still have complete access to their funds due to multi-sig. Users can still use the two accounts they control to move their funds out of their account without using the tipping bot.

Writing the NEM Tipbot for Reddit

The NEM Tipbot for Reddit was built on node.js using the NEM-sdk which is available via

npm install nem-sdk

In addition to the NEM-sdk, we use Sequelize for storing our accounts in a SQL database (sqlite by default), and Snoowrap to monitor Reddit comments.

Full source-code for the NEM Tipbot is available on GitHub

The NEM Tipbot has a few responsibilities as outlined below

  • Allow a Reddit user to register with bot
    • Monitor PMs for the trigger phrase register in the body/subject
    • Generate and store a challenge code associated to that reddit user.
    • Reply to the PM providing instructions to the Reddit user.
    • Monitor the NEM blockchain for transactions to said NEM account that contain the user’s challenge code and public address.
    • Once said transaction is received and the challenge code is verified convert the NEM account to a multi-sig account using the sender’s public-key, the supplied public-key in the message, and the receiving account public-key.
  • Allow user to tip other users on reddit
    • Monitor reddit comments for the trigger phrase !tipxem in the body.
    • If the receiving Reddit user has never been tipped, generate a NEM account on their behalf.
    • Generate a multi-sig transfer transaction to the receiving user’s account and post it to the NEM network.
    • Reply to the original Reddit comment notifying the receiving user of their tip.

I won’t detail every aspect of the code but instead highlight the more interesting pieces.

One of the most important pieces during the registration process is converting an account to a multi-sig account.

Here’s a snippet of code responsible for that process:

...
var common = nem.model.objects.create("common")(WALLET_PASSWORD, userCommon.privateKey);
var publicAddress = nem.model.address.toAddress(originPublicKey, NETWORK);

var kp = nem.crypto.keyPair.create(cosignerCommon.privateKey);

var multisigAggregateModificationTransaction =
    {
        isMultiSig: false,
        modifications: [
            {
                'modificationType': 1,
                'cosignatoryAccount': originPublicKey
            },
            {
                'modificationType': 1,
                'cosignatoryAccount': publicKey
            },
            {
                'modificationType': 1,
                'cosignatoryAccount': kp.publicKey.toString()
            }
        ],
        minCosignatories: {
            "relativeChange": 2
        },
        relativeChange: 2
    }

console.log(multisigAggregateModificationTransaction);

var prepareMultisigAggModTransaction = nem.model.transactions.prepare("multisigAggregateModificationTransaction");

var preparedMultisigAggModTransaction = prepareMultisigAggModTransaction(common, multisigAggregateModificationTransaction, NETWORK);
...

In order to convert an account to a multi-sig account we must create a multisig aggregated modification transaction, that’s a mouthful but essentially we create a special type of transaction that modifies an account and adds co-signatories. When we create the multisigAggregateModificationTransaction object we add 3 co-signatories, the two that are controlled by the user, and the one that the bot controls. Pretty simple, then all we need to do is prepare the transaction and publish it to the network.

Another interesting piece of code to look at is the following function walletToWallet which we use to generate a multi-sig transaction from one user to another

function walletToWallet(fromUserWallet, fromUserCosignerWallet, toUserWallet, amount) {
    var fromUserAccount = getFirstAccount(fromUserWallet);
    var fromUserCosignerAccount = getFirstAccount(fromUserCosignerWallet);
    var toUserAccount = getFirstAccount(toUserWallet);

    //  Multi-sig account
    var fromUserDecrypted = {
        password: WALLET_PASSWORD
    };

    var algo = fromUserAccount.algo;

    nem.crypto.helpers.passwordToPrivatekey(fromUserDecrypted, fromUserAccount, algo);

    var fromUserCommon = nem.model.objects.create("common")(WALLET_PASSWORD, fromUserDecrypted.privateKey);

    var fromUserKp = nem.crypto.keyPair.create(fromUserDecrypted.privateKey);


    //  Cosigner-account
    var fromUserCosignerDecrypted = {
        password: WALLET_PASSWORD
    };

    algo = fromUserCosignerAccount.algo;

    nem.crypto.helpers.passwordToPrivatekey(fromUserCosignerDecrypted, fromUserCosignerAccount, algo);

    var fromUserCosignerCommon = nem.model.objects.create("common")(WALLET_PASSWORD, fromUserCosignerDecrypted.privateKey);

    var fromUserCosignerKp = nem.crypto.keyPair.create(fromUserCosignerDecrypted.privateKey);

    //  Create multi-sig transfer transaction
    var transferTransaction = nem.model.objects.create("transferTransaction")(toUserAccount.address, amount);
    transferTransaction.isMultisig = true;
    transferTransaction.multisigAccount = { publicKey: fromUserKp.publicKey.toString() };

    var prepareTransferTransaction = nem.model.transactions.prepare("transferTransaction");

    var preparedTransferTransaction = prepareTransferTransaction(fromUserCosignerCommon, transferTransaction, NETWORK);

    var endpoint = nem.model.objects.create("endpoint")(ENDPOINT, nem.model.nodes.defaultPort);

    nem.model.transactions.send(fromUserCosignerCommon, preparedTransferTransaction, endpoint).then((res) => {
        console.log(res);
    });
}

In order to generate a simple multi-sig transaction we need four things:

  • The public key of the multi-sig account we’re sending from
  • The private key of the cosignatory account
  • The public key of the receiving account
  • The amount of XEM we want to send

The first half of the code simply derives the public and private key for the multi-sig and cosignatory accounts respectively. The last piece of the code generates the transfer transaction, prepares it, and broadcasts it to the XEM network.

One of the challenges with the NEM tipbot is in monitoring the incoming registration transactions. To do this we utilize the NEM-sdk’s websocket functionality. Every-time a new block is received we filter out all transactions based on the following criteria:

  • Has this transaction already been processed?

  • Is the receiving address a user that has already registered with the tip bot?

     function processBlock(block) {
         console.log("Processing block: ");
     
         var transactions = block['transactions'];
     
         User.findAll({
             attributes: ['address'],
             where: {
                 address: {
                     $ne: null
                 },
                 $or: [
                     {
                         registered: {
                             $eq: null
                         }
                     },
                     {
                         registered: {
                             $eq: false
                         }
                     },
                 ]
             }
         }).then(res => {
             var monitoredAddresses = _.pluck(res, 'address');
     
             var filteredTxs = _.filter(transactions, function (tx) {
                 return _.indexOf(monitoredAddresses, tx.recipient) != -1;
             });
     
             for (var i = 0; i < filteredTxs.length; ++i) {
                 processTransaction(filteredTxs[i]);
             }
     
             console.log("Monitored Addresses: " + monitoredAddresses);
             console.log("Filtered Txs: " + filteredTxs);
         });
     }
    

The remaining transactions are then processed further to verify their contents and purpose. The bulk of this work is done in the processTransaction function.

The following function is what we use to monitor Reddit comments:

function monitorComments() {
    let tipCommentStream = snooStream.commentStream(SUBREDDIT, { regex: /!tipxem\s+((?=.*\d)\d*(?:\.\d+)?)/i, rate: 30000 });

    tipCommentStream.on('post', (comment, match) => {
        var tipAmount = parseFloat(match[1]).toFixed(6);

        //  Don't try to tip if this number isn't valid.
        if (isFinite(tipAmount) && tipAmount > 0) {
            attemptTip(comment, tipAmount);
        }
    });
}

Every-time a comment is posted we use a regex filter to grab comments that contain the trigger phrase !tipxem and parse the tip amount.

Future Plans

Future plans to extend the bot include adding support for NEM Authenticator. We also plan to add support for tipping in mosaics as-well.