├── .gitignore ├── examples └── usage.js ├── lib └── main.js ├── license.md ├── package.json └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea 3 | atlassian-ide-plugin.xml -------------------------------------------------------------------------------- /examples/usage.js: -------------------------------------------------------------------------------- 1 | var bitmessage = require('../lib/main')('localhost', 8442, 'user', 'password'); 2 | 3 | try { 4 | bitmessage.messages.sent.list(function(value) { 5 | console.dir(value); 6 | }); 7 | } 8 | catch(err) { 9 | console.dir(err); 10 | } -------------------------------------------------------------------------------- /lib/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var xmlrpc = require('xmlrpc') 4 | , moment = require('moment'); 5 | 6 | module.exports = function (host, port, user, pass, options) { 7 | var defaults = options || {}; 8 | var client = xmlrpc.createClient({ 9 | host: host, 10 | port: port, 11 | path: '/', 12 | basic_auth: { 13 | user: user, 14 | pass: pass 15 | } 16 | }); 17 | 18 | var callMethod = function (options, cb) { 19 | options = options || {}; 20 | options.args = options.args || []; 21 | if (options.json === undefined) 22 | options.json = true; 23 | 24 | client.methodCall(options.method, options.args, function (error, value) { 25 | if (error) throw error; 26 | if (options.json) return cb(JSON.parse(value)); 27 | return cb(value); 28 | }); 29 | }; 30 | 31 | var fromBase64 = function (value) { 32 | return new Buffer(value, 'base64').toString(); 33 | }; 34 | 35 | var toBase64 = function (value) { 36 | return new Buffer(value).toString('base64'); 37 | }; 38 | 39 | var fromUnix = function (value) { 40 | return moment.unix(parseInt(value, 10)).toDate(); 41 | }; 42 | 43 | return { 44 | addresses: { 45 | list: function (cb) { 46 | //listAddresses is deprecated in 0.4.0 47 | callMethod({ method: 'listAddresses2' }, function (value) { 48 | var addresses = value.addresses; 49 | 50 | for (var i = 0; i < addresses.length; ++i) { 51 | addresses[i].label = fromBase64(addresses[i].label); 52 | } 53 | 54 | cb(addresses); 55 | }); 56 | }, 57 | createRandom: function (label, cb) { 58 | callMethod({ 59 | method: 'createRandomAddress', 60 | args: [toBase64(label)], 61 | json: false 62 | }, cb); 63 | }, 64 | createDeterministic: function (passphrase, cb) { 65 | callMethod({ 66 | method: 'createDeterministicAddresses', 67 | args: [toBase64(passphrase), 1, 0, 0, false, 1, 1] 68 | }, function (value) { 69 | if (value.addresses.length > 0) { 70 | return cb(value.addresses[0]); 71 | } 72 | return cb(null); 73 | }); 74 | }, 75 | getDeterministic: function (passphrase, cb) { 76 | callMethod({ 77 | method: 'getDeterministicAddress', 78 | args: [toBase64(passphrase), 3, 1], 79 | json: false 80 | }, cb); 81 | }, 82 | }, 83 | messages: { 84 | inbox: { 85 | list: function (cb) { 86 | callMethod({method: 'getAllInboxMessages' }, function (value) { 87 | var messages = value.inboxMessages; 88 | for (var i = 0; i < messages.length; ++i) { 89 | messages[i].subject = fromBase64(messages[i].subject); 90 | messages[i].message = fromBase64(messages[i].message); 91 | messages[i].receivedTime = fromUnix(messages[i].receivedTime); 92 | } 93 | cb(messages); 94 | }); 95 | }, 96 | single: function (messageId, cb, read) { 97 | var args = [messageId]; 98 | 99 | //optionally mark a message as read or unread 100 | if ( read === true || read === false ) { 101 | args.push(read); 102 | } 103 | 104 | callMethod({ 105 | method: 'getInboxMessageById', 106 | args: args 107 | }, function (value) { 108 | var message = value.inboxMessage[0]; 109 | message.subject = fromBase64(message.subject); 110 | message.message = fromBase64(message.message); 111 | message.receivedTime = fromUnix(message.receivedTime); 112 | cb(message); 113 | }); 114 | }, 115 | moveToTrash: function (messageId, cb) { 116 | callMethod({ 117 | method: 'trashMessage', 118 | args: [messageId], 119 | json: false 120 | }, function (value) { 121 | cb(value); 122 | }); 123 | }, 124 | }, 125 | sent: { 126 | list: function (cb) { 127 | callMethod({method: 'getAllSentMessages' }, function (value) { 128 | var messages = value.sentMessages; 129 | for (var i = 0; i < messages.length; ++i) { 130 | messages[i].subject = fromBase64(messages[i].subject); 131 | messages[i].message = fromBase64(messages[i].message); 132 | messages[i].lastActionTime = fromUnix(messages[i].lastActionTime); 133 | } 134 | cb(messages); 135 | }); 136 | }, 137 | single: function (messageId, cb) { 138 | callMethod({ 139 | method: 'getSentMessageById', 140 | args: [messageId] 141 | }, function (value) { 142 | var message = value.sentMessage[0]; 143 | message.subject = fromBase64(message.subject); 144 | message.message = fromBase64(message.message); 145 | message.lastActionTime = fromUnix(message.lastActionTime); 146 | cb(message); 147 | }); 148 | }, 149 | singleByAck: function (ackData, cb) { 150 | callMethod({ 151 | method: 'getSentMessageByAckData', 152 | args: [ackData] 153 | }, function (value) { 154 | var message = value.sentMessage[0]; 155 | message.subject = fromBase64(message.subject); 156 | message.message = fromBase64(message.message); 157 | message.lastActionTime = fromUnix(message.lastActionTime); 158 | cb(message); 159 | }); 160 | }, 161 | moveToTrashByAck: function (ackData, cb) { 162 | callMethod({ 163 | method: 'trashSentMessageByAckData', 164 | args: [ackData], 165 | json: false 166 | }, function (value) { 167 | cb(value); 168 | }); 169 | }, 170 | }, 171 | send: function (toAddress, fromAddress, subject, message, cb) { 172 | callMethod({ 173 | method: 'sendMessage', 174 | args: [toAddress, fromAddress, toBase64(subject), toBase64(message)], 175 | json: false 176 | }, cb); 177 | }, 178 | broadcast: function (fromAddress, subject, message, cb) { 179 | callMethod({ 180 | method: 'sendBroadcast', 181 | args: [fromAddress, toBase64(subject), toBase64(message)], 182 | json: false 183 | }, cb); 184 | }, 185 | status: function (messageId, cb) { 186 | callMethod({ 187 | method: 'getStatus', 188 | args: [messageId], 189 | json: false 190 | }, cb); 191 | } 192 | }, 193 | subscriptions: { 194 | list: function (cb) { 195 | callMethod({ method: 'listSubscriptions' }, function (value) { 196 | var subscriptions = value.subscriptions; 197 | 198 | for (var i = 0; i < subscriptions.length; ++i) { 199 | subscriptions[i].label = fromBase64(subscriptions[i].label); 200 | } 201 | 202 | cb(subscriptions); 203 | }); 204 | }, 205 | subscribe: function (address, label, cb) { 206 | callMethod({ 207 | method: 'addSubscription', 208 | args: [address, toBase64(label)], 209 | json: false 210 | }, cb); 211 | }, 212 | unsubscribe: function (address, cb) { 213 | callMethod({ 214 | method: 'deleteSubscription', 215 | args: [address], 216 | json: false 217 | }, cb); 218 | } 219 | }, 220 | addressbook: { 221 | list: function (cb) { 222 | callMethod({ method: 'listAddressBookEntries' }, function (value) { 223 | var addresses = value.addresses; 224 | 225 | for (var i = 0; i < addresses.length; ++i) { 226 | addresses[i].label = fromBase64(addresses[i].label); 227 | } 228 | 229 | cb(addresses); 230 | }); 231 | }, 232 | addEntry: function (address, label, cb) { 233 | callMethod({ 234 | method: 'addAddressBookEntry', 235 | args: [address, toBase64(label)], 236 | json: false 237 | }, cb); 238 | }, 239 | deleteEntry: function (address, cb) { 240 | callMethod({ 241 | method: 'deleteAddressBookEntry', 242 | args: [address], 243 | json: false 244 | }, cb); 245 | } 246 | }, 247 | test: { 248 | add: function (a, b, cb) { 249 | callMethod({ 250 | method: 'add', 251 | args: [a, b], 252 | json: false 253 | }, cb); 254 | }, 255 | hello: function (word, word2, cb) { 256 | callMethod({ 257 | method: 'helloWorld', 258 | args: [word, word2], 259 | json: false 260 | }, cb); 261 | }, 262 | }, 263 | }; 264 | } -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2013 Rex Morgan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 6 | software and associated documentation files (the “Software”), to deal in the Software 7 | without restriction, including without limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 9 | to whom the Software is furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 15 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 16 | PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 17 | FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19 | DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bitmessage-node", 3 | "description": "Node wrapper for bitmessage client api", 4 | "version": "0.1.5", 5 | "dependencies": { 6 | "xmlrpc": "1.1.0", 7 | "moment": "2.0.0" 8 | }, 9 | "keywords": ["bitmessage", "crypto", "anonymous", "api", "wrapper"], 10 | "homepage": "https://github.com/rexmorgan/bitmessage-node", 11 | "author": "Rex Morgan (http://rexflex.net)", 12 | "main": "./lib/main.js", 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/rexmorgan/bitmessage-node.git" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Archived 2 | ========= 3 | 4 | This project is now archived. Please feel free to fork it if needed. 5 | 6 | bitmessage-node 7 | ========= 8 | 9 | 10 | [![NPM](https://nodei.co/npm/bitmessage-node.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/bitmessage-node/) 11 | 12 | Bitmessage client for the API written in Node.js. 13 | 14 | 15 | ## Install 16 | 17 | npm install bitmessage-node 18 | 19 | ## Usage 20 | 21 | //establish connection to Bitmessage server 22 | var bm = require('bitmessage-node')(host, port, username, password); 23 | 24 | //get inbox list 25 | bm.messages.inbox.list(cb); //returns list of messages 26 | 27 | //get message by id 28 | bm.messages.inbox.single(id, cb, read); 29 | 30 | //send message 31 | bm.messages.send(toAddress, fromAddress, subject, message, cb); 32 | 33 | //get sent messages 34 | bm.messages.sent.list(cb); 35 | 36 | //get sent message by id 37 | bm.messages.sent.single(id, cb); 38 | 39 | //get sent message by ack 40 | bm.messages.sent.singleByAck(ack, cb); 41 | 42 | //move message to trash by id 43 | bm.messages.inbox.moveToTrash(id, cb); 44 | 45 | //move message to trash by ack 46 | bm.messages.sent.moveToTrashByAck(ack, cb); 47 | 48 | //list identities 49 | bm.addresses.list(cb); //returns identities 50 | 51 | //create random address 52 | bm.addresses.createRandom(label, cb); //returns address id 53 | 54 | //create deterministic address 55 | bm.addresses.createDeterministic(passphrase, cb); //returns address id 56 | 57 | //list subscriptions 58 | bm.subscriptions.list(cb); //returns subscriptions 59 | 60 | //subscribe 61 | bm.subscriptions.subscribe(address, label, cb); //returns string with status 62 | 63 | //unsubscribe 64 | bm.subscriptions.unsubscribe(address, cb); //returns string with status 65 | 66 | //list contacts 67 | bm.addressbook.list(cb); //returns contacts 68 | 69 | //add contact 70 | bm.addressbook.addEntry(address, label, cb); 71 | 72 | //delete contact 73 | bm.addressbook.deleteEntry(address, cb); 74 | 75 | ## Requirements 76 | 77 | A Bitmessage server running on a local machine. Download from [Bitmessage.org](http://bitmessage.org) 78 | 79 | If you plan on connecting to a remote Bitmessage server, you should *absolutely* use SSH tunneling to establish a secure connection and connect via a local port. 80 | 81 | ssh -N -L 8442:localhost:8442 82 | 83 | 84 | ## More info 85 | 86 | * [Bitmessage.org](http://bitmessage.org) 87 | * [API Reference](https://bitmessage.org/wiki/API_Reference#List_of_Operations) 88 | 89 | 90 | The MIT License (MIT) 91 | 92 | --------------------------------------------------------------------------------