├── .gitignore ├── README.md ├── example-bundle.js ├── example.js ├── index.js ├── package.json └── test ├── sample.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ccurl.interface.js 2 | 3 | This is a simple node script that makes it possible to interface directly with the [cCurl Library](#https://github.com/iotaledger/ccurl) via Node-FFI. What this is for is basically for doing Proof of Work without IRI Core. Hashing with cCurl is also arguably faster. 4 | 5 | ## Install 6 | 7 | You can simply install this package with all its dependencies (iota.lib.js and ffi) via npm: 8 | ``` 9 | $ npm install ccurl.interface.js 10 | ``` 11 | 12 | After that, you will have to compile cCurl locally on your machine. Follow the instructions on the [official repo here](#https://github.com/iotaledger/ccurl). 13 | ``` 14 | $ git clone https://github.com/iotaledger/ccurl.git 15 | $ mkdir build && cd build && cmake .. && cd .. && make -C build 16 | ``` 17 | 18 | Then copy the `libccurl` library from the `build/lib` folder to the main directory. 19 | 20 | 21 | ## How to use 22 | 23 | Using this library is fairly simple. You can optionally provide the full path where you have your compiled libccurl. 24 | 25 | ### API 26 | 27 | ``` 28 | ccurl( 29 | trunkTransaction: string, 30 | branchTransaction: string, 31 | trytes: string[], 32 | minWeightMagnitude: number, 33 | path?: string, 34 | callback?: (error: Error, result: string[]) => void 35 | ): EventEmitter | void 36 | ``` 37 | 38 | When no callback is passed, the method returns an `EventEmitter` which allows you to track job progress. You must call `start` to begin the job. 39 | 40 | #### Events: 41 | 42 | - `'progress'`: Callback `result` is a number between 0 and 1 as a fraction of `trytes.length` 43 | - `'done'`: Callback `result` is the array of tryte strings 44 | 45 | #### Methods: 46 | 47 | - `start: () => void`: Begin the job. 48 | 49 | #### Example: 50 | 51 | ``` 52 | const ccurl = require('ccurl.interface.js') 53 | 54 | const job = ccurl(trunkTransaction, branchTransaction, trytes, minWeightMagnitude, [, path]) 55 | 56 | job.on('progress', (err, progress) => { 57 | console.log(progress) // A number between 0 and 1 as a percentage of `trytes.length` 58 | }) 59 | 60 | job.on('done', callback) 61 | 62 | job.start() 63 | ``` 64 | 65 | See `example.js` or `test/test.js`. 66 | -------------------------------------------------------------------------------- /example-bundle.js: -------------------------------------------------------------------------------- 1 | var tst = require("./index"); 2 | 3 | tst("NJLOHTMMCCXNBGQLULHAQLSFNKSMPVMMFUVEYNSPWPR9BSQZAF9NTZOXZDKLKE9VIGWHE99GFYXRA9999", "OWUTOWLQTXSNOGFXV99VEDHU9DEQIULPLISHQQXUKT9HYDDCIVXQPORBCBXRNZOERHSSCEDNNXX999999", 13, ["999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999BHPGS9FVELSFEDMIBDRZKIJQRQCPXYFAYTADQDWJESZGKXLZFKXZRGQDXJ9F9ATA9VCDRHVFONUZUJHIQML9999999999999999999999999NO9999999999999999999999999HQLVHVD99C99999999C99999999OHWJBLSVQJRVJVIMNJPSZSIDVWKGXONCT9DWJNROWGYUWQOFYXZZBLXILCGGWSRQVRQSDKFUUVPIIBXYX999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", "ZISQTVPNM9BBUNZGHFRYGKOBILSDHTZNOYTLZPBMKFPHXPJZJU9EVPMGI9PS9ZCL9SQHPVMSTUZUNYD9WHYJJJJLQUGYRQKIZYUUDHCLVPRUKRSRATPVUYTEQWPGMLPYTCXRGXUDSTPJZSPSPMEKRSOFHC9YPRCMDWOETOLPZBAHXKBDNSFLATTZLIZMFGWXPTFYFPMOYWEVYFI9BLIYP9XUGESUTIKKPVXSUCOOHGWOKDVICMDSEYO9CBLOAXMIT9ZLIQBMJWDC9XTGLDB9YIGRKLJLRBRDEHEGSAMGHCQYYGBCENHKQTCVLSAZYXEWXDICDESNAYADPFXQWPNBDADLVPVPHQI9IWCMDBKD9RBGAD9EFFYEDMBTDA9ALHTSLCRXLZIDRNPUUVYFYNFFDUWYSVNYTAYAGEULEDIOBVMEEMHEOJIGUVMLANYUCPPNC9YETYSCAT9GGTNGKDASFQHMHFXMEWZLNAJSCMO9YROBWXHRLZVRSDCPZVOZBVKKSDYDU9SWHBZPXKCEOWVMKYTOATZNDRXLFCGOBWEELABDQERBKZUFDWXWICHXDNQBTKLBT9UQYS9IVUBTRB9LOVONISWRYEQAYJF9YR9XUDGX9BDGYXPRJDGYNIAKUOEJDXZUNLLRVIYQBYXJCQHXYPX9XOMMGVNKZPUUUIJ9SUCW9AFUDLGR9PAQL9XXQRGZDJBBDSTDJFCPFBCEEFQZUXBLVEJEJ9HTQTXLXM9NNTFZYZDNGNTTSGTGNATMCUZPRWTK9YYRJT9OJNXWTEPZFFRKZPFKOJACTHHZWPNRDUAKBFWJRLGFSKBVQPVGWON9PG9W9SY9KGJSCLJLAUEWLTQPNNGJAINCIHS9UKDKBFGBVOEOKTRIGKLAD9BEA9DFAU9JNIFTMALTSIGZFPQCFOWJBGWVOOYTRJZBUGCSGAHXCDDGNQNXBTKYIEGSCKZLKBG99CSTS9PSRZB9OIZABLIUUTYYCRZHPD9TIVBMTHXVETHCIYXYM9UIFFRUZ9S9HEZTWGIL9TEEIBEKUXP9NGMBXOJGBCAD9DHSIKAVG9QLBCMJDSJJXTFWCROVJUSRMJTJJSSOPWBEMC9KOLTZICBXWSTFIN9FFJLWFZZLVOVJYMRFLAEAPKNDPSKFQUGLMDGBEALKSZ9SMGNZYXTABJPYOKOUUREUCCVPTKQQMUSTARGVEWOWF99RPVPAGNDNUNCRFNUUBFOKYPMYMBVQKSQNQJCJWHHJTYLUHXGZRPWGRUOCIZTVXXLBWPTXBITLMFWAFKQLGXCKSYXYWWEVMXWVJODWMQYBAJWTLSKIRISQ9ICVCERFIZNDVBY9NWFJOHJWOZYLIISOPCPPRBZWLBUIOSOERPIJUGMCALEHKMNVSLXHYOFTVOYLKNLHZZIOAHHZMUMOYTJCFBFRJBXCTWUYKF9NJUHZOOFUCZTGNPSVD9MBZFMSNXXNJNWBOKCVBVHUJVPPPC9QLTXUQWIYHDQPKHECROLSGZXFYRKRBUCA9ZZHKWGXCJPYDRN9WZVHLXFXADBUBZHLZXRAXJ9JLBTLF9CCFBXEXUIMFQCL9KFGOOBIRFWTRDXQNFKLYRBIIHSHCDZLUVVRIKMUUCOKZYT9BIBDM9AKCYBPQMNTFYRLKZSFEBHZZEBWGPGAYNEPBZOOUDONTLOTQLXJFVYHXOCICCAEAXPRDVEPCFHVRQONQPLKVTDZXXA9M9X9PJQIZMQUWNSMNIPVBQZZJOFIRJKZZIRTMKOHKWUMVWIATDDDILUOYOXP99TZBKPFZBVCQ9VYTRUQKY9UBZHIPNHEAERJX9MJMYGRW9SKCENLZRHIAIKINN9XAENRI9KXDAQOYSM9CDBMMOBFF9MRDGCFBSAXOKSGAKZKJHZDQKRDXXGGOMASBDUVREEIOUMSOQNYFPOFUC9HDEPYDRHFFKNJYVTKVNYNTCNSOUNLKWPFJEISPDXDNVWSSSGVJSWVUMTYGQSFJKMSJGUZUSSQS9SNNJOZAUSWQLSJUSKGHTSUYOIHRYZNHQYJBFLNGFKWTZWSYMARWODNZTVILDFJXMYUXYFGHDQHFFOBIOQZBVFCIFPFUOJQNJWMKPAGONTW9BSZTSDCGPFVQBJQYYHZGKUGWO9XRHCNDYABYNPMLMEFFLCCWCCGBBRVZAF9EVXEZJBGSHHVFUBHBR9VIQCX9RCRRCGBYBKNCNOQZSUXLLITTOXTLRDYQZQIMYBGJTDTG9RFGYWU9MNKLLESUXCSNX9FSLYQDVGV999999999999999999999999999NO9999999999999999999999999EQLVHVD99B99999999C99999999OHWJBLSVQJRVJVIMNJPSZSIDVWKGXONCT9DWJNROWGYUWQOFYXZZBLXILCGGWSRQVRQSDKFUUVPIIBXYX999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", "JBCFFBUVSFJNLUNLWGQKXYPUYUIOMAAXSGPVZLCIZKCIGILUKUJEUQOOIXIPPZWG9EIFHTMZBGGBLFNAAPK9EUOQBXZGHHSIVBKKTBHXLEVOJDHHJETH9AWULLYYPCTILIHLLJXIZVBUN9URJR9RLBVKRHLCXYDABICEZRMX9LLZIIXFVYSZDCKTKZKRJ99CJVMCILWMDMJSULINXVNYOYLELRXWUERUKPJJGGDRVBVAWZPHEUIZDCWZKSJSFBPMVTXLWTPNCFFA9KGCJMGSFHQTOBUPMWNCGYDQEEAXCEYNCOYLMAKIRRDWTIOKMK99ORBQOKFWSVLH9KNNIKARSFKUHGYYFVTXWYAUEXZGCYHIPVGFMJPKPANIEGYOFUAICHZ9IDFMDGDZV9PGE9OAXEEDBOBKHZTRGKVPSAEIDCMKJFAAKZQUTE9LL9WA9WZGZPDYD9SZNEMSDQGDCSCQMKEBVFDWDGZFNBWBP9KPPEBSXECO9VDQYOSDEKBI9LDWERMNLHDJKPABCEJOWMYTMENFCPHVXBGHQFQLNRDXSKTZDLUHTAOOXFLUVKISBYNHNY9ZJLJBKDUKAWN9H9ASDRZEBKLKTRYSBAXLNITGPZHLOAUWIAQCMWXVYGRTUKLXGRPZPFAVLLBZCUIHOAOXGHEMFSPIADZYVEKZPRCAASAWOJGDORHMWGUECNWTIEZYJAIYTKPTGNAPKUJNLXQGXWZFXYHOIZSNZLJSGDUSZWOAANACUOBOVDHBTEVMGJVFSPNSJZAYVKEHPX9G9NRIDGWFZQLIDEAQFKNRRIDFAOPFZBBOQDQXWF9OVLXZVPXIXYMOUEVIKEZAPAKBKXQFZIYNW9EZIT9CTRSFSLBAMKBHHURGMXXTQBUMFWOSGFDKCUXCIZZXSJMXTNXZPQCHUBSUUYSQYYPGKAOMLXD9CBZAXJVCIAYHAVIQZKRFFLOIM9CNVRTI9QXJHCRXNEKEHOGOPBEZZWKUGQBPEIMG9SFHJWDBVVPEDVFTKRBQUUDX9C9RYIDYHJESFL9FXYTKYZPFJFUGBDSDY9XUOE9MUZLVHXNTWPJAGLSFOHGBL9ZNLXDIJYNONJSGMZPVVLMVIQULVBKHVWBPGJPATNVTJYIHCEFTJILAO9FF9WMSN99JCVSME9QHLNHPFIFLEK9ZPJHUMDHKJLOQIAVPBPSCRQJIGW9ZLCLVJVNCU9XWWAHJPDL9SECECTTYMRMGXT9RUKKRTLQQCSBIDER9CWZGXGSTRNNIGCATUFVKOPQGKDPSRZJFEHWIHISYHEZCYSBIUBSHPFKXARSHUQASP99WDBEAP9OFRCXONGTZQBCHHRRDBT9FOGZFXAIHZXSKNQUYXLMYKBLBBVDHHB9EVEVRJHJOHSPDMCQCWKWANEYNOKOBBOS9RAVQOOXDQMWQEAZIJMGBOQEGSSFDEHOMCHUPKCDTBHHSEGRYSEXQOZOCWYHGIYJWWEFDPQKAFZJFPRDFNASETEHDCGGNCKWVAIMQP9NHUJJOZABASFDU9YOAUAZA9LQNQH99MSMYVSMMXUTP9OGBEFYEBUQGNMYEOARCYZGPJKHUGMEDFBMJMMUHYW9HSBECKZQLQFANQIGTLWIHGBE9AHHTMOBPFJVMZWWQQUNGRRFCAZGR9OCYCQTOHFMZXOBTJKMHOUGIRXIRVIXKTYNQIHYJGO9TEMQCUOOLZSVXTXKQSTZJINUDZLZWTXMKNNUEPCTYBDJMTNMWXEG9EJJHUIWLESMZEJEFYAVIMCLRQJETRFMV9VYNCYFWSQZXPBQWTHECRKNAQDDFGONNRBBTSSEYSSGWABGHDUBFOXGYBBGRNMNXLRBNHYKREPSLENOGCZSUNHQMNCMTIMNH9QIVNFIGMRBVIAWBMBYAGXNEIRAJUHJHACJNXNJVYYNBPXJXZSOOTFVJZYCOZIBHWGCLCVVDQTBOWJKH9INGUXHNETYGAQKVFMLTGERBPBOIJXNZO9IU9HPBWADDMQEZUBLZNBWBNXAXNMZOHDZTWWGMB9DGILBAFDSEEHIYEBPUTMQODTBQCEXYPFMRFADDFHJFBQMJSFXNOWX9CHL9CJXZVYY9QNWWCQAEAOSEVLRMPQVHNEKJUNPGACZSIJGPLWXIOZTGYOGKSHKERSJNVZPTDTAZU9ANXEPLVUFJLCCQGZKRWXQAEATVIQCX9RCRRCGBYBKNCNOQZSUXLLITTOXTLRDYQZQIMYBGJTDTG9RFGYWU9MNKLLESUXCSNX9FSLYQDVGVMDY999999999999999999999999NO9999999999999999999999999EQLVHVD99A99999999C99999999OHWJBLSVQJRVJVIMNJPSZSIDVWKGXONCT9DWJNROWGYUWQOFYXZZBLXILCGGWSRQVRQSDKFUUVPIIBXYX999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", "NO999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999HJ9KPCKKRQYJRTLABUZANHRGBR9MPWZDZRQSXWCVMDXKOEFKFVXBETLZQBANHTDWSVDHNN9WFZPY9HSANAJA999999999999999999999999NO9999999999999999999999999AQLVHVD99999999999C99999999OHWJBLSVQJRVJVIMNJPSZSIDVWKGXONCT9DWJNROWGYUWQOFYXZZBLXILCGGWSRQVRQSDKFUUVPIIBXYX999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"], function(e,s) { 4 | console.log(e,s); 5 | }) 6 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | var tst = require("./index"); 2 | 3 | tst("NJLOHTMMCCXNBGQLULHAQLSFNKSMPVMMFUVEYNSPWPR9BSQZAF9NTZOXZDKLKE9VIGWHE99GFYXRA9999", "OWUTOWLQTXSNOGFXV99VEDHU9DEQIULPLISHQQXUKT9HYDDCIVXQPORBCBXRNZOERHSSCEDNNXX999999", 13, ["999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999BHPGS9FVELSFEDMIBDRZKIJQRQCPXYFAYTADQDWJESZGKXLZFKXZRGQDXJ9F9ATA9VCDRHVFONUZUJHIQML9999999999999999999999999NO9999999999999999999999999HQLVHVD99C99999999C99999999OHWJBLSVQJRVJVIMNJPSZSIDVWKGXONCT9DWJNROWGYUWQOFYXZZBLXILCGGWSRQVRQSDKFUUVPIIBXYX999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"], function(e,s) { 4 | console.log(e,s); 5 | }) 6 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const EventEmitter = require('events'); 4 | const IOTA = require('iota.lib.js'); 5 | const ffi = require('ffi'); 6 | const fs = require('fs'); 7 | 8 | module.exports = function(trunkTransaction, branchTransaction, minWeightMagnitude, trytes, ccurlPath, callback) { 9 | // Set up the emitter and emit functions 10 | let emitter; 11 | 12 | if (!callback) { 13 | emitter = new EventEmitter(); 14 | } 15 | 16 | function finishWithError(message) { 17 | const err = typeof message === 'string' ? new Error(message) : message; 18 | 19 | if (callback) { 20 | callback(err, null); 21 | } else { 22 | emitter.emit('done', err, null); 23 | } 24 | } 25 | 26 | function reportProgress(count) { 27 | if (emitter) { 28 | emitter.emit('progress', null, count / trytes.length); 29 | } 30 | } 31 | 32 | function finishWithResult(result) { 33 | if (callback) { 34 | callback(null, result); 35 | } else { 36 | emitter.emit('done', null, result); 37 | } 38 | } 39 | 40 | // If no file path provided, switch arguments 41 | if (arguments.length === 5 && Object.prototype.toString.call(ccurlPath) === "[object Function]") { 42 | callback = ccurlPath; 43 | ccurlPath = __dirname; 44 | } else if (arguments.length === 4) { 45 | ccurlPath = __dirname; 46 | } 47 | 48 | // Declare IOTA library 49 | const iota = new IOTA(); 50 | 51 | const isValid = () => { 52 | // inputValidator: Check if correct hash 53 | if (!iota.valid.isHash(trunkTransaction)) { 54 | return finishWithError("Invalid trunkTransaction"); 55 | } 56 | 57 | // inputValidator: Check if correct hash 58 | if (!iota.valid.isHash(branchTransaction)) { 59 | return finishWithError("Invalid branchTransaction"); 60 | } 61 | 62 | // inputValidator: Check if int 63 | if (!iota.valid.isValue(minWeightMagnitude)) { 64 | return finishWithError("Invalid minWeightMagnitude"); 65 | } 66 | 67 | // inputValidator: Check if array of trytes 68 | if (!iota.valid.isArrayOfTrytes(trytes)) { 69 | return finishWithError("Invalid trytes supplied"); 70 | } 71 | 72 | // Check if file path exists 73 | if (!fs.existsSync(ccurlPath)) { 74 | return finishWithError("Incorrect file path!"); 75 | } 76 | 77 | return true; 78 | } 79 | 80 | const fullPath = ccurlPath + '/libccurl'; 81 | 82 | // Define libccurl to be used for finding the nonce 83 | const libccurl = ffi.Library(fullPath, { 84 | ccurl_pow : [ 'string', [ 'string', 'int'] ] 85 | }); 86 | 87 | const finalBundleTrytes = []; 88 | let previousTxHash; 89 | let i = 0; 90 | 91 | function loopTrytes() { 92 | // Validation check must be done here since this is the entry point for the event emitter 93 | if (isValid()) { 94 | getBundleTrytes(trytes[i], function(error) { 95 | 96 | if (error) { 97 | 98 | return finishWithError(error); 99 | 100 | } else { 101 | 102 | i++; 103 | 104 | if (i < trytes.length) { 105 | 106 | reportProgress(i); 107 | loopTrytes(); 108 | 109 | } else { 110 | 111 | // reverse the order so that it's ascending from currentIndex 112 | return finishWithResult(finalBundleTrytes.reverse()); 113 | 114 | } 115 | } 116 | }); 117 | } 118 | } 119 | 120 | function getBundleTrytes(thisTrytes, bundleCallback) { 121 | // PROCESS LOGIC: 122 | // Start with last index transaction 123 | // Assign it the trunk / branch which the user has supplied 124 | // IF there is a bundle, chain the bundle transactions via 125 | // trunkTransaction together 126 | 127 | // If this is the first transaction, to be processed 128 | // Make sure that it's the last in the bundle and then 129 | // assign it the supplied trunk and branch transactions 130 | if (!previousTxHash) { 131 | 132 | const txObject = iota.utils.transactionObject(thisTrytes); 133 | 134 | // Check if last transaction in the bundle 135 | if (txObject.lastIndex !== txObject.currentIndex) { 136 | return bundleCallback(new Error("Wrong bundle order. The bundle should be ordered in descending order from currentIndex")); 137 | } 138 | 139 | txObject.trunkTransaction = trunkTransaction; 140 | txObject.branchTransaction = branchTransaction; 141 | txObject.attachmentTimestamp = Date.now(); 142 | txObject.attachmentTimestampLowerBound = 0; 143 | txObject.attachmentTimestampUpperBound = (Math.pow(3,27) - 1) / 2; 144 | 145 | const newTrytes = iota.utils.transactionTrytes(txObject); 146 | 147 | // cCurl updates the nonce as well as the transaction hash 148 | libccurl.ccurl_pow.async(newTrytes, minWeightMagnitude, function(error, returnedTrytes) { 149 | 150 | if (error) { 151 | return bundleCallback(error); 152 | } 153 | 154 | const newTxObject= iota.utils.transactionObject(returnedTrytes); 155 | 156 | // Assign the previousTxHash to this tx 157 | const txHash = newTxObject.hash; 158 | previousTxHash = txHash; 159 | 160 | finalBundleTrytes.push(returnedTrytes); 161 | 162 | return bundleCallback(null); 163 | }); 164 | 165 | } else { 166 | 167 | const txObject = iota.utils.transactionObject(thisTrytes); 168 | 169 | // Chain the bundle together via the trunkTransaction (previous tx in the bundle) 170 | // Assign the supplied trunkTransaciton as branchTransaction 171 | txObject.trunkTransaction = previousTxHash; 172 | txObject.branchTransaction = trunkTransaction; 173 | txObject.attachmentTimestamp = Date.now(); 174 | txObject.attachmentTimestampLowerBound = 0; 175 | txObject.attachmentTimestampUpperBound = (Math.pow(3,27) - 1) / 2; 176 | 177 | const newTrytes = iota.utils.transactionTrytes(txObject); 178 | 179 | // cCurl updates the nonce as well as the transaction hash 180 | libccurl.ccurl_pow.async(newTrytes, minWeightMagnitude, function(error, returnedTrytes) { 181 | 182 | if (error) { 183 | 184 | return bundleCallback(error); 185 | } 186 | 187 | const newTxObject= iota.utils.transactionObject(returnedTrytes); 188 | 189 | // Assign the previousTxHash to this tx 190 | const txHash = newTxObject.hash; 191 | previousTxHash = txHash; 192 | 193 | finalBundleTrytes.push(returnedTrytes); 194 | 195 | return bundleCallback(null); 196 | }); 197 | } 198 | } 199 | 200 | if (emitter) { 201 | emitter.start = loopTrytes 202 | 203 | return emitter; 204 | } 205 | 206 | loopTrytes(); 207 | } 208 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ccurl.interface.js", 3 | "version": "0.0.9", 4 | "description": "ccurl interface for nodejs", 5 | "main": "index.js", 6 | "engines" : { 7 | "node" : ">=4" 8 | }, 9 | "scripts": { 10 | "lint": "eslint index.js", 11 | "test": "node test/test.js" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/iotaledger/ccurl.interface.js.git" 16 | }, 17 | "keywords": [ 18 | "iota", 19 | "curl", 20 | "ccurl", 21 | "nodejs", 22 | "interface" 23 | ], 24 | "author": "Dominik Schiener (IOTA Foundation)", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/iotaledger/ccurl.interface.js/issues" 28 | }, 29 | "homepage": "https://github.com/iotaledger/ccurl.interface.js#readme", 30 | "dependencies": { 31 | "ffi": "^2.2.0", 32 | "iota.lib.js": "^0.4.3" 33 | }, 34 | "devDependencies": { 35 | "eslint": "^4.15.0" 36 | }, 37 | "eslintConfig": { 38 | "extends": "eslint:recommended", 39 | "parserOptions": { 40 | "ecmaVersion": 6 41 | }, 42 | "env": { 43 | "es6": true, 44 | "node": true 45 | }, 46 | "rules": { 47 | "no-var": "error" 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /test/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "trunkTransaction": "LLJDW9NTJHKYWIWEGIF9WDQCNHGGJOUHMYLGAOAUOFKWTFFFNSAJLBJTHWQAWFBNAPZAXKXWNL9K99999", 3 | "branchTransaction": "LLJDW9NTJHKYWIWEGIF9WDQCNHGGJOUHMYLGAOAUOFKWTFFFNSAJLBJTHWQAWFBNAPZAXKXWNL9K99999", 4 | "minWeightMagnitude": 2, 5 | "trytes": [ 6 | "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999A9RGRKVGWMWMKOLVMDFWJUHNUNYWZTJADGGPZGXNLERLXYWJE9WQHWWBMCPZMVVMJUMWWBLZLNMLDCGDJ999999999999999999999999999999999999999999999999999999YGYQIVD99999999999999999999TXEFLKNPJRBYZPORHZU9CEMFIFVVQBUSTDGSJCZMBTZCDTTJVUFPTCCVHHORPMGCURKTH9VGJIXUQJVHK999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", 7 | "BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDW99999999999999999PGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /* eslint-disable no-console, no-unused-vars */ 4 | const assert = require('assert'); 5 | const fs = require('fs'); 6 | 7 | const ccurl = require('../index'); 8 | 9 | if (!fs.existsSync(process.env.CCURL_PATH)) { 10 | console.log('Usage:\n\tCCURL_PATH=/path/to/ccurl npm test') 11 | process.exit() 12 | } 13 | 14 | const sampleData = require('./sample.json'); 15 | const trunkTransaction = sampleData.trunkTransaction 16 | const branchTransaction = sampleData.branchTransaction 17 | const minWeightMagnitude = sampleData.minWeightMagnitude 18 | const trytes = sampleData.trytes 19 | 20 | const testCallback = () => new Promise((resolve, reject) => { 21 | ccurl(trunkTransaction, branchTransaction, minWeightMagnitude, trytes, process.env.CCURL_PATH, (err, result) => { 22 | if (err) { 23 | reject(err); 24 | return; 25 | } 26 | 27 | assert.equal(result.length, trytes.length); 28 | console.log('\n' + trytes.length + ' transactions hashed.\nOK'); 29 | resolve(); 30 | }); 31 | }) 32 | 33 | const testEmitter = () => new Promise((resolve, reject) => { 34 | const jobEmitter = ccurl(trunkTransaction, branchTransaction, minWeightMagnitude, trytes, process.env.CCURL_PATH); 35 | 36 | jobEmitter.on('progress', (err, progress) => { 37 | if (err) { 38 | return reject(err); 39 | } 40 | 41 | assert.equal(progress, 0.5); 42 | console.log('Progress reported: ' + progress + '\nOK'); 43 | }) 44 | 45 | jobEmitter.on('done', (err, result) => { 46 | if (err) { 47 | return reject(err); 48 | } 49 | 50 | assert.equal(result.length, trytes.length); 51 | console.log('\n' + trytes.length + ' transactions hashed.\nOK'); 52 | console.log('Job done emitted.\nOK') 53 | resolve(); 54 | }); 55 | }) 56 | 57 | testCallback().then(() => { 58 | return testEmitter(); 59 | }).catch(err => { 60 | console.error(err); 61 | process.exit(1); 62 | }) 63 | --------------------------------------------------------------------------------