@leofcoin/chain 1.3.11 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/block-worker.js +1 -1
- package/demo/chain.browser.js +4 -0
- package/dist/browser/workers/block-worker.js +1977 -5692
- package/dist/browser/workers/machine-worker.js +1955 -5670
- package/dist/browser/workers/pool-worker.js +1636 -5531
- package/dist/browser/workers/transaction-worker.js +1626 -5521
- package/dist/chain.js +9865 -1192
- package/dist/client-80bc8156.js +491 -0
- package/dist/commonjs-7fe3c381.js +270 -0
- package/dist/generate-account-445db122.js +46 -0
- package/dist/index-57f93805.js +718 -0
- package/dist/{messages.browser.js → messages-bce1b91d-81af3b00.js} +26 -39
- package/dist/module/chain.js +9820 -1174
- package/dist/module/client-8031ec88.js +489 -0
- package/dist/module/commonjs-9005d5c0.js +268 -0
- package/dist/module/generate-account-489552b6.js +44 -0
- package/dist/module/index-ac2285c4.js +688 -0
- package/dist/module/messages-bce1b91d-eaf75d83.js +302 -0
- package/dist/module/node.js +6833 -2
- package/dist/module/workers/block-worker.js +3 -287
- package/dist/module/workers/machine-worker.js +3 -287
- package/dist/node.js +6845 -8
- package/dist/workers/machine-worker.js +1 -1
- package/package.json +11 -20
- package/src/chain.js +9 -12
- package/src/contract.js +2 -2
- package/src/machine.js +10 -7
- package/src/node.js +2 -2
- package/src/transaction.js +5 -5
- package/test/chain.js +5 -7
- package/test/index.js +1 -3
- package/tsconfig.js +15 -0
- package/workers/block-worker.js +40 -0
- package/workers/machine-worker.js +219 -0
- package/workers/pool-worker.js +28 -0
- package/workers/transaction-worker.js +20 -0
- package/workers/workers.js +9 -0
- package/dist/865.browser.js +0 -10
- package/dist/chain.browser.js +0 -66838
- package/dist/generate-account.browser.js +0 -50
- package/dist/multi-wallet.browser.js +0 -15
- package/dist/node.browser.js +0 -9858
- package/dist/pako.browser.js +0 -6900
- package/dist/peernet-swarm.browser.js +0 -839
- package/dist/storage.browser.js +0 -3724
- package/dist/wrtc.browser.js +0 -28
- package/rollup.config.js +0 -229
- package/src/standards/initializer.js +0 -10
- package/webpack.config.js +0 -109
|
@@ -0,0 +1,718 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var bs58Check = require('bs58check');
|
|
4
|
+
var bip32 = require('bip32');
|
|
5
|
+
var randombytes = require('randombytes');
|
|
6
|
+
require('@ethersproject/bignumber');
|
|
7
|
+
require('@ethersproject/units');
|
|
8
|
+
var secp256k1 = require('secp256k1');
|
|
9
|
+
var hashWasm = require('hash-wasm');
|
|
10
|
+
var base58 = require('@vandeurenglenn/base58');
|
|
11
|
+
var base32 = require('@vandeurenglenn/base32');
|
|
12
|
+
var varint = require('varint');
|
|
13
|
+
|
|
14
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
15
|
+
|
|
16
|
+
function _interopNamespace(e) {
|
|
17
|
+
if (e && e.__esModule) return e;
|
|
18
|
+
var n = Object.create(null);
|
|
19
|
+
if (e) {
|
|
20
|
+
Object.keys(e).forEach(function (k) {
|
|
21
|
+
if (k !== 'default') {
|
|
22
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
23
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
get: function () { return e[k]; }
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
n["default"] = e;
|
|
31
|
+
return Object.freeze(n);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
var bs58Check__default = /*#__PURE__*/_interopDefaultLegacy(bs58Check);
|
|
35
|
+
var bip32__namespace = /*#__PURE__*/_interopNamespace(bip32);
|
|
36
|
+
var randombytes__default = /*#__PURE__*/_interopDefaultLegacy(randombytes);
|
|
37
|
+
var secp256k1__default = /*#__PURE__*/_interopDefaultLegacy(secp256k1);
|
|
38
|
+
var base58__default = /*#__PURE__*/_interopDefaultLegacy(base58);
|
|
39
|
+
var base32__default = /*#__PURE__*/_interopDefaultLegacy(base32);
|
|
40
|
+
var varint__default = /*#__PURE__*/_interopDefaultLegacy(varint);
|
|
41
|
+
|
|
42
|
+
var testnets = {
|
|
43
|
+
'leofcoin:olivia': {
|
|
44
|
+
messagePrefix: '\u0019Leofcoin Signed Message:',
|
|
45
|
+
pubKeyHash: 0x73, // o
|
|
46
|
+
scriptHash: 0x76, // p
|
|
47
|
+
multiTxHash: 0x8b4125, // omtx
|
|
48
|
+
payments: {
|
|
49
|
+
version: 0,
|
|
50
|
+
unspent: 0x1fa443d7 // ounsp
|
|
51
|
+
},
|
|
52
|
+
wif: 0x7D, // s
|
|
53
|
+
multiCodec: 0x7c4,
|
|
54
|
+
bip32: { public: 0x13BBF2D5, private: 0x13BBCBC5 }
|
|
55
|
+
},
|
|
56
|
+
'bitcoin:testnet': {
|
|
57
|
+
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
|
58
|
+
bech32: 'tb',
|
|
59
|
+
pubKeyHash: 0x6f,
|
|
60
|
+
scriptHash: 0xc4,
|
|
61
|
+
wif: 0xef,
|
|
62
|
+
bip32: {
|
|
63
|
+
public: 0x043587cf,
|
|
64
|
+
private: 0x04358394
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
// https://en.bitcoin.it/wiki/List_of_address_prefixes
|
|
71
|
+
/**
|
|
72
|
+
* Main network
|
|
73
|
+
* @return {messagePrefix, pubKeyHash, scriptHash, wif, bip32}
|
|
74
|
+
*/
|
|
75
|
+
const leofcoin = {
|
|
76
|
+
messagePrefix: '\u0019Leofcoin Signed Message:',
|
|
77
|
+
pubKeyHash: 0x30, // L
|
|
78
|
+
scriptHash: 0x37, // P
|
|
79
|
+
multiTxHash: 0x3adeed, // Lmtx
|
|
80
|
+
payments: {
|
|
81
|
+
version: 0,
|
|
82
|
+
unspent: 0x0d6e0327 // Lunsp
|
|
83
|
+
},
|
|
84
|
+
coin_type: 640,
|
|
85
|
+
wif: 0x3F, // S
|
|
86
|
+
multiCodec: 0x3c4,
|
|
87
|
+
bip32: { public: 0x13BBF2D4, private: 0x13BBCBC4 },
|
|
88
|
+
testnet: testnets['leofcoin:olivia']
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const bitcoin = {
|
|
92
|
+
messagePrefix: '\x18Bitcoin Signed Message:\n',
|
|
93
|
+
bech32: 'bc',
|
|
94
|
+
pubKeyHash: 0x00,
|
|
95
|
+
multiCodec: 0x00,
|
|
96
|
+
scriptHash: 0x05,
|
|
97
|
+
wif: 0x80,
|
|
98
|
+
coin_type: 0,
|
|
99
|
+
bip32: {
|
|
100
|
+
public: 0x0488b21e, private: 0x0488ade4
|
|
101
|
+
},
|
|
102
|
+
testnet: testnets['bitcoin:testnet']
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const litecoin = {
|
|
106
|
+
messagePrefix: '\x19Litecoin Signed Message:\n',
|
|
107
|
+
pubKeyHash: 0x30,
|
|
108
|
+
scriptHash: 0x32,
|
|
109
|
+
wif: 0xb0,
|
|
110
|
+
bip32: {
|
|
111
|
+
public: 0x019da462,
|
|
112
|
+
private: 0x019d9cfe
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const ethereum = {
|
|
117
|
+
messagePrefix: '\x19Ethereum Signed Message:\n',
|
|
118
|
+
pubKeyHash: 0x30,
|
|
119
|
+
scriptHash: 0x32,
|
|
120
|
+
bip32: {
|
|
121
|
+
private: 0x0488ADE4, public: 0x0488B21E
|
|
122
|
+
},
|
|
123
|
+
coin_type: 60,
|
|
124
|
+
wif: 0x45,//E
|
|
125
|
+
multiCodec: 0x3c5
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Our & supported networks
|
|
130
|
+
* @return {leofcoin, olivia}
|
|
131
|
+
*/
|
|
132
|
+
var networks = {
|
|
133
|
+
leofcoin,
|
|
134
|
+
bitcoin,
|
|
135
|
+
litecoin,
|
|
136
|
+
ethereum
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const fromNetworkString = network => {
|
|
140
|
+
const parts = network.split(':');
|
|
141
|
+
network = networks[parts[0]];
|
|
142
|
+
if (parts[1]) {
|
|
143
|
+
if (network[parts[1]]) network = network[parts[1]];
|
|
144
|
+
|
|
145
|
+
network.coin_type = 1;
|
|
146
|
+
}
|
|
147
|
+
return network;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
// see https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt
|
|
151
|
+
|
|
152
|
+
var wordlist = ["abandon","ability","able","about","above","absent","absorb","abstract","absurd","abuse","access","accident","account","accuse","achieve","acid","acoustic","acquire","across","act","action","actor","actress","actual","adapt","add","addict","address","adjust","admit","adult","advance","advice","aerobic","affair","afford","afraid","again","age","agent","agree","ahead","aim","air","airport","aisle","alarm","album","alcohol","alert","alien","all","alley","allow","almost","alone","alpha","already","also","alter","always","amateur","amazing","among","amount","amused","analyst","anchor","ancient","anger","angle","angry","animal","ankle","announce","annual","another","answer","antenna","antique","anxiety","any","apart","apology","appear","apple","approve","april","arch","arctic","area","arena","argue","arm","armed","armor","army","around","arrange","arrest","arrive","arrow","art","artefact","artist","artwork","ask","aspect","assault","asset","assist","assume","asthma","athlete","atom","attack","attend","attitude","attract","auction","audit","august","aunt","author","auto","autumn","average","avocado","avoid","awake","aware","away","awesome","awful","awkward","axis","baby","bachelor","bacon","badge","bag","balance","balcony","ball","bamboo","banana","banner","bar","barely","bargain","barrel","base","basic","basket","battle","beach","bean","beauty","because","become","beef","before","begin","behave","behind","believe","below","belt","bench","benefit","best","betray","better","between","beyond","bicycle","bid","bike","bind","biology","bird","birth","bitter","black","blade","blame","blanket","blast","bleak","bless","blind","blood","blossom","blouse","blue","blur","blush","board","boat","body","boil","bomb","bone","bonus","book","boost","border","boring","borrow","boss","bottom","bounce","box","boy","bracket","brain","brand","brass","brave","bread","breeze","brick","bridge","brief","bright","bring","brisk","broccoli","broken","bronze","broom","brother","brown","brush","bubble","buddy","budget","buffalo","build","bulb","bulk","bullet","bundle","bunker","burden","burger","burst","bus","business","busy","butter","buyer","buzz","cabbage","cabin","cable","cactus","cage","cake","call","calm","camera","camp","can","canal","cancel","candy","cannon","canoe","canvas","canyon","capable","capital","captain","car","carbon","card","cargo","carpet","carry","cart","case","cash","casino","castle","casual","cat","catalog","catch","category","cattle","caught","cause","caution","cave","ceiling","celery","cement","census","century","cereal","certain","chair","chalk","champion","change","chaos","chapter","charge","chase","chat","cheap","check","cheese","chef","cherry","chest","chicken","chief","child","chimney","choice","choose","chronic","chuckle","chunk","churn","cigar","cinnamon","circle","citizen","city","civil","claim","clap","clarify","claw","clay","clean","clerk","clever","click","client","cliff","climb","clinic","clip","clock","clog","close","cloth","cloud","clown","club","clump","cluster","clutch","coach","coast","coconut","code","coffee","coil","coin","collect","color","column","combine","come","comfort","comic","common","company","concert","conduct","confirm","congress","connect","consider","control","convince","cook","cool","copper","copy","coral","core","corn","correct","cost","cotton","couch","country","couple","course","cousin","cover","coyote","crack","cradle","craft","cram","crane","crash","crater","crawl","crazy","cream","credit","creek","crew","cricket","crime","crisp","critic","crop","cross","crouch","crowd","crucial","cruel","cruise","crumble","crunch","crush","cry","crystal","cube","culture","cup","cupboard","curious","current","curtain","curve","cushion","custom","cute","cycle","dad","damage","damp","dance","danger","daring","dash","daughter","dawn","day","deal","debate","debris","decade","december","decide","decline","decorate","decrease","deer","defense","define","defy","degree","delay","deliver","demand","demise","denial","dentist","deny","depart","depend","deposit","depth","deputy","derive","describe","desert","design","desk","despair","destroy","detail","detect","develop","device","devote","diagram","dial","diamond","diary","dice","diesel","diet","differ","digital","dignity","dilemma","dinner","dinosaur","direct","dirt","disagree","discover","disease","dish","dismiss","disorder","display","distance","divert","divide","divorce","dizzy","doctor","document","dog","doll","dolphin","domain","donate","donkey","donor","door","dose","double","dove","draft","dragon","drama","drastic","draw","dream","dress","drift","drill","drink","drip","drive","drop","drum","dry","duck","dumb","dune","during","dust","dutch","duty","dwarf","dynamic","eager","eagle","early","earn","earth","easily","east","easy","echo","ecology","economy","edge","edit","educate","effort","egg","eight","either","elbow","elder","electric","elegant","element","elephant","elevator","elite","else","embark","embody","embrace","emerge","emotion","employ","empower","empty","enable","enact","end","endless","endorse","enemy","energy","enforce","engage","engine","enhance","enjoy","enlist","enough","enrich","enroll","ensure","enter","entire","entry","envelope","episode","equal","equip","era","erase","erode","erosion","error","erupt","escape","essay","essence","estate","eternal","ethics","evidence","evil","evoke","evolve","exact","example","excess","exchange","excite","exclude","excuse","execute","exercise","exhaust","exhibit","exile","exist","exit","exotic","expand","expect","expire","explain","expose","express","extend","extra","eye","eyebrow","fabric","face","faculty","fade","faint","faith","fall","false","fame","family","famous","fan","fancy","fantasy","farm","fashion","fat","fatal","father","fatigue","fault","favorite","feature","february","federal","fee","feed","feel","female","fence","festival","fetch","fever","few","fiber","fiction","field","figure","file","film","filter","final","find","fine","finger","finish","fire","firm","first","fiscal","fish","fit","fitness","fix","flag","flame","flash","flat","flavor","flee","flight","flip","float","flock","floor","flower","fluid","flush","fly","foam","focus","fog","foil","fold","follow","food","foot","force","forest","forget","fork","fortune","forum","forward","fossil","foster","found","fox","fragile","frame","frequent","fresh","friend","fringe","frog","front","frost","frown","frozen","fruit","fuel","fun","funny","furnace","fury","future","gadget","gain","galaxy","gallery","game","gap","garage","garbage","garden","garlic","garment","gas","gasp","gate","gather","gauge","gaze","general","genius","genre","gentle","genuine","gesture","ghost","giant","gift","giggle","ginger","giraffe","girl","give","glad","glance","glare","glass","glide","glimpse","globe","gloom","glory","glove","glow","glue","goat","goddess","gold","good","goose","gorilla","gospel","gossip","govern","gown","grab","grace","grain","grant","grape","grass","gravity","great","green","grid","grief","grit","grocery","group","grow","grunt","guard","guess","guide","guilt","guitar","gun","gym","habit","hair","half","hammer","hamster","hand","happy","harbor","hard","harsh","harvest","hat","have","hawk","hazard","head","health","heart","heavy","hedgehog","height","hello","helmet","help","hen","hero","hidden","high","hill","hint","hip","hire","history","hobby","hockey","hold","hole","holiday","hollow","home","honey","hood","hope","horn","horror","horse","hospital","host","hotel","hour","hover","hub","huge","human","humble","humor","hundred","hungry","hunt","hurdle","hurry","hurt","husband","hybrid","ice","icon","idea","identify","idle","ignore","ill","illegal","illness","image","imitate","immense","immune","impact","impose","improve","impulse","inch","include","income","increase","index","indicate","indoor","industry","infant","inflict","inform","inhale","inherit","initial","inject","injury","inmate","inner","innocent","input","inquiry","insane","insect","inside","inspire","install","intact","interest","into","invest","invite","involve","iron","island","isolate","issue","item","ivory","jacket","jaguar","jar","jazz","jealous","jeans","jelly","jewel","job","join","joke","journey","joy","judge","juice","jump","jungle","junior","junk","just","kangaroo","keen","keep","ketchup","key","kick","kid","kidney","kind","kingdom","kiss","kit","kitchen","kite","kitten","kiwi","knee","knife","knock","know","lab","label","labor","ladder","lady","lake","lamp","language","laptop","large","later","latin","laugh","laundry","lava","law","lawn","lawsuit","layer","lazy","leader","leaf","learn","leave","lecture","left","leg","legal","legend","leisure","lemon","lend","length","lens","leopard","lesson","letter","level","liar","liberty","library","license","life","lift","light","like","limb","limit","link","lion","liquid","list","little","live","lizard","load","loan","lobster","local","lock","logic","lonely","long","loop","lottery","loud","lounge","love","loyal","lucky","luggage","lumber","lunar","lunch","luxury","lyrics","machine","mad","magic","magnet","maid","mail","main","major","make","mammal","man","manage","mandate","mango","mansion","manual","maple","marble","march","margin","marine","market","marriage","mask","mass","master","match","material","math","matrix","matter","maximum","maze","meadow","mean","measure","meat","mechanic","medal","media","melody","melt","member","memory","mention","menu","mercy","merge","merit","merry","mesh","message","metal","method","middle","midnight","milk","million","mimic","mind","minimum","minor","minute","miracle","mirror","misery","miss","mistake","mix","mixed","mixture","mobile","model","modify","mom","moment","monitor","monkey","monster","month","moon","moral","more","morning","mosquito","mother","motion","motor","mountain","mouse","move","movie","much","muffin","mule","multiply","muscle","museum","mushroom","music","must","mutual","myself","mystery","myth","naive","name","napkin","narrow","nasty","nation","nature","near","neck","need","negative","neglect","neither","nephew","nerve","nest","net","network","neutral","never","news","next","nice","night","noble","noise","nominee","noodle","normal","north","nose","notable","note","nothing","notice","novel","now","nuclear","number","nurse","nut","oak","obey","object","oblige","obscure","observe","obtain","obvious","occur","ocean","october","odor","off","offer","office","often","oil","okay","old","olive","olympic","omit","once","one","onion","online","only","open","opera","opinion","oppose","option","orange","orbit","orchard","order","ordinary","organ","orient","original","orphan","ostrich","other","outdoor","outer","output","outside","oval","oven","over","own","owner","oxygen","oyster","ozone","pact","paddle","page","pair","palace","palm","panda","panel","panic","panther","paper","parade","parent","park","parrot","party","pass","patch","path","patient","patrol","pattern","pause","pave","payment","peace","peanut","pear","peasant","pelican","pen","penalty","pencil","people","pepper","perfect","permit","person","pet","phone","photo","phrase","physical","piano","picnic","picture","piece","pig","pigeon","pill","pilot","pink","pioneer","pipe","pistol","pitch","pizza","place","planet","plastic","plate","play","please","pledge","pluck","plug","plunge","poem","poet","point","polar","pole","police","pond","pony","pool","popular","portion","position","possible","post","potato","pottery","poverty","powder","power","practice","praise","predict","prefer","prepare","present","pretty","prevent","price","pride","primary","print","priority","prison","private","prize","problem","process","produce","profit","program","project","promote","proof","property","prosper","protect","proud","provide","public","pudding","pull","pulp","pulse","pumpkin","punch","pupil","puppy","purchase","purity","purpose","purse","push","put","puzzle","pyramid","quality","quantum","quarter","question","quick","quit","quiz","quote","rabbit","raccoon","race","rack","radar","radio","rail","rain","raise","rally","ramp","ranch","random","range","rapid","rare","rate","rather","raven","raw","razor","ready","real","reason","rebel","rebuild","recall","receive","recipe","record","recycle","reduce","reflect","reform","refuse","region","regret","regular","reject","relax","release","relief","rely","remain","remember","remind","remove","render","renew","rent","reopen","repair","repeat","replace","report","require","rescue","resemble","resist","resource","response","result","retire","retreat","return","reunion","reveal","review","reward","rhythm","rib","ribbon","rice","rich","ride","ridge","rifle","right","rigid","ring","riot","ripple","risk","ritual","rival","river","road","roast","robot","robust","rocket","romance","roof","rookie","room","rose","rotate","rough","round","route","royal","rubber","rude","rug","rule","run","runway","rural","sad","saddle","sadness","safe","sail","salad","salmon","salon","salt","salute","same","sample","sand","satisfy","satoshi","sauce","sausage","save","say","scale","scan","scare","scatter","scene","scheme","school","science","scissors","scorpion","scout","scrap","screen","script","scrub","sea","search","season","seat","second","secret","section","security","seed","seek","segment","select","sell","seminar","senior","sense","sentence","series","service","session","settle","setup","seven","shadow","shaft","shallow","share","shed","shell","sheriff","shield","shift","shine","ship","shiver","shock","shoe","shoot","shop","short","shoulder","shove","shrimp","shrug","shuffle","shy","sibling","sick","side","siege","sight","sign","silent","silk","silly","silver","similar","simple","since","sing","siren","sister","situate","six","size","skate","sketch","ski","skill","skin","skirt","skull","slab","slam","sleep","slender","slice","slide","slight","slim","slogan","slot","slow","slush","small","smart","smile","smoke","smooth","snack","snake","snap","sniff","snow","soap","soccer","social","sock","soda","soft","solar","soldier","solid","solution","solve","someone","song","soon","sorry","sort","soul","sound","soup","source","south","space","spare","spatial","spawn","speak","special","speed","spell","spend","sphere","spice","spider","spike","spin","spirit","split","spoil","sponsor","spoon","sport","spot","spray","spread","spring","spy","square","squeeze","squirrel","stable","stadium","staff","stage","stairs","stamp","stand","start","state","stay","steak","steel","stem","step","stereo","stick","still","sting","stock","stomach","stone","stool","story","stove","strategy","street","strike","strong","struggle","student","stuff","stumble","style","subject","submit","subway","success","such","sudden","suffer","sugar","suggest","suit","summer","sun","sunny","sunset","super","supply","supreme","sure","surface","surge","surprise","surround","survey","suspect","sustain","swallow","swamp","swap","swarm","swear","sweet","swift","swim","swing","switch","sword","symbol","symptom","syrup","system","table","tackle","tag","tail","talent","talk","tank","tape","target","task","taste","tattoo","taxi","teach","team","tell","ten","tenant","tennis","tent","term","test","text","thank","that","theme","then","theory","there","they","thing","this","thought","three","thrive","throw","thumb","thunder","ticket","tide","tiger","tilt","timber","time","tiny","tip","tired","tissue","title","toast","tobacco","today","toddler","toe","together","toilet","token","tomato","tomorrow","tone","tongue","tonight","tool","tooth","top","topic","topple","torch","tornado","tortoise","toss","total","tourist","toward","tower","town","toy","track","trade","traffic","tragic","train","transfer","trap","trash","travel","tray","treat","tree","trend","trial","tribe","trick","trigger","trim","trip","trophy","trouble","truck","true","truly","trumpet","trust","truth","try","tube","tuition","tumble","tuna","tunnel","turkey","turn","turtle","twelve","twenty","twice","twin","twist","two","type","typical","ugly","umbrella","unable","unaware","uncle","uncover","under","undo","unfair","unfold","unhappy","uniform","unique","unit","universe","unknown","unlock","until","unusual","unveil","update","upgrade","uphold","upon","upper","upset","urban","urge","usage","use","used","useful","useless","usual","utility","vacant","vacuum","vague","valid","valley","valve","van","vanish","vapor","various","vast","vault","vehicle","velvet","vendor","venture","venue","verb","verify","version","very","vessel","veteran","viable","vibrant","vicious","victory","video","view","village","vintage","violin","virtual","virus","visa","visit","visual","vital","vivid","vocal","voice","void","volcano","volume","vote","voyage","wage","wagon","wait","walk","wall","walnut","want","warfare","warm","warrior","wash","wasp","waste","water","wave","way","wealth","weapon","wear","weasel","weather","web","wedding","weekend","weird","welcome","west","wet","whale","what","wheat","wheel","when","where","whip","whisper","wide","width","wife","wild","will","win","window","wine","wing","wink","winner","winter","wire","wisdom","wise","wish","witness","wolf","woman","wonder","wood","wool","word","work","world","worry","worth","wrap","wreck","wrestle","wrist","write","wrong","yard","year","yellow","you","young","youth","zebra","zero","zone","zoo"];
|
|
153
|
+
|
|
154
|
+
const {subtle} = crypto;
|
|
155
|
+
|
|
156
|
+
const uint8ArrayToHex = uint8Array =>
|
|
157
|
+
[...uint8Array].map(x => x.toString(16).padStart(2, '0')).join('');
|
|
158
|
+
|
|
159
|
+
const arrayBufferToHex = arrayBuffer =>
|
|
160
|
+
uint8ArrayToHex(new Uint8Array(arrayBuffer));
|
|
161
|
+
|
|
162
|
+
const hexToUint8Array = hex =>
|
|
163
|
+
new Uint8Array(hex.match(/[\da-f]{2}/gi).map(x => parseInt(x, 16)));
|
|
164
|
+
|
|
165
|
+
const generatePbkdf2 = async (password) => {
|
|
166
|
+
return subtle.importKey(
|
|
167
|
+
'raw',
|
|
168
|
+
password,
|
|
169
|
+
'PBKDF2',
|
|
170
|
+
false,
|
|
171
|
+
['deriveBits']
|
|
172
|
+
)
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const pbkdf2 = async (password, salt, iterations = 4096, length = 64, hash = 'SHA-512') => {
|
|
176
|
+
const key = await generatePbkdf2(password);
|
|
177
|
+
const bits = await subtle.deriveBits({
|
|
178
|
+
name: 'PBKDF2',
|
|
179
|
+
hash,
|
|
180
|
+
salt: salt,
|
|
181
|
+
iterations,
|
|
182
|
+
}, key, length);
|
|
183
|
+
return bits;
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
const generateAesKey = async (length = 256) => {
|
|
187
|
+
const key = await subtle.generateKey({
|
|
188
|
+
name: 'AES-CBC',
|
|
189
|
+
length
|
|
190
|
+
}, true, ['encrypt', 'decrypt']);
|
|
191
|
+
|
|
192
|
+
return key;
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const importAesKey = async (exported, format = 'raw', length = 256) => {
|
|
196
|
+
return await subtle.importKey(format, exported, {
|
|
197
|
+
name: 'AES-CBC',
|
|
198
|
+
length
|
|
199
|
+
}, true, ['encrypt', 'decrypt'])
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
const exportAesKey = async (key, format = 'raw') => {
|
|
203
|
+
return await subtle.exportKey(format, key)
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const encryptAes = async (uint8Array, key, iv) => subtle.encrypt({
|
|
207
|
+
name: 'AES-CBC',
|
|
208
|
+
iv,
|
|
209
|
+
}, key, uint8Array);
|
|
210
|
+
|
|
211
|
+
const decryptAes = async (uint8Array, key, iv) => subtle.decrypt({
|
|
212
|
+
name: 'AES-CBC',
|
|
213
|
+
iv,
|
|
214
|
+
}, key, uint8Array);
|
|
215
|
+
|
|
216
|
+
const encrypt = async string => {
|
|
217
|
+
const ec = new TextEncoder();
|
|
218
|
+
const key = await generateAesKey();
|
|
219
|
+
const iv = await randombytes__default["default"](16);
|
|
220
|
+
const ciphertext = await encryptAes(ec.encode(string), key, iv);
|
|
221
|
+
const exported = await exportAesKey(key);
|
|
222
|
+
return {
|
|
223
|
+
key: arrayBufferToHex(exported),
|
|
224
|
+
iv: iv.toString('hex'),
|
|
225
|
+
cipher: arrayBufferToHex(ciphertext)
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const decrypt = async (cipher, key, iv) => {
|
|
230
|
+
if (!key.type) key = await importAesKey(hexToUint8Array(key));
|
|
231
|
+
cipher = new Uint8Array(hexToUint8Array(cipher));
|
|
232
|
+
iv = new Uint8Array(hexToUint8Array(iv));
|
|
233
|
+
|
|
234
|
+
const dec = new TextDecoder();
|
|
235
|
+
const plaintext = await decryptAes(cipher, key, iv);
|
|
236
|
+
|
|
237
|
+
return dec.decode(plaintext);
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const createHash = async (data, algorithm = 'SHA-512') => {
|
|
241
|
+
return await subtle.digest(algorithm, data)
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
class Mnemonic {
|
|
245
|
+
constructor(options = {}) {
|
|
246
|
+
if (!options.wordlist) this.wordlist = wordlist; // english always loaded, rest included by dev
|
|
247
|
+
else this.wordlist = options.wordlist;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
lpad(string, padString, length) {
|
|
251
|
+
while (string.length < length) {
|
|
252
|
+
string = padString + string;
|
|
253
|
+
}
|
|
254
|
+
return string;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
normalize(string) {
|
|
258
|
+
return (string || '').normalize('NFKD');
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
bytesToBinary(bytes) {
|
|
262
|
+
return bytes.map(byte => this.lpad(byte.toString(2), '0', 8)).join('');
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
async deriveChecksumBits(entropyBuffer) {
|
|
266
|
+
const entropy = entropyBuffer.length * 8;
|
|
267
|
+
const cs = entropy / 32;
|
|
268
|
+
const hash = await createHash(entropyBuffer, 'SHA-512');
|
|
269
|
+
return this.bytesToBinary(Array.from(hash)).slice(0, cs);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async mnemonicFromEntropy(entropy) {
|
|
273
|
+
if (!Buffer.isBuffer(entropy)) entropy = Buffer.from(entropy, 'hex');
|
|
274
|
+
let checksum = await this.deriveChecksumBits(entropy);
|
|
275
|
+
console.log(checksum);
|
|
276
|
+
entropy = this.bytesToBinary(Array.from(entropy));
|
|
277
|
+
let bits = entropy + checksum;
|
|
278
|
+
bits = bits.match(/(.{1,11})/g);
|
|
279
|
+
return bits.map(binary => {
|
|
280
|
+
const index = parseInt(binary, 2);
|
|
281
|
+
return this.wordlist[index]
|
|
282
|
+
}).join(' ')
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
*
|
|
287
|
+
* @param {Number} strength 256 / 8 = 32 = 24 words
|
|
288
|
+
* @returns {String}
|
|
289
|
+
*/
|
|
290
|
+
generate(strength = 256) {
|
|
291
|
+
return this.mnemonicFromEntropy(randombytes__default["default"](strength / 8))
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
salt(password) {
|
|
295
|
+
return 'mnemonic' + this.normalize(password);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
seedFromMnemonic(mnemonic, password) {
|
|
299
|
+
const encoder =new TextEncoder();
|
|
300
|
+
return pbkdf2(
|
|
301
|
+
encoder.encode(this.normalize(mnemonic)),
|
|
302
|
+
encoder.encode(this.salt(password)),
|
|
303
|
+
4096,
|
|
304
|
+
64,
|
|
305
|
+
'SHA-512')
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const { publicKeyConvert } = secp256k1__default["default"];
|
|
310
|
+
|
|
311
|
+
const publicKeyToEthereumAddress = async (publicKeyBuffer) => {
|
|
312
|
+
let uncompressed = publicKeyConvert(publicKeyBuffer, false);
|
|
313
|
+
const hasher = await hashWasm.createKeccak(256);
|
|
314
|
+
hasher.update(uncompressed);
|
|
315
|
+
|
|
316
|
+
const hash = hasher.digest();
|
|
317
|
+
return `0x${hash.slice(-40).toString('hex')}`
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
class HDWallet {
|
|
321
|
+
|
|
322
|
+
get chainCodeBuffer() {
|
|
323
|
+
return this.ifNotLocked(() => this.hdnode.chainCode)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
get chainCode() {
|
|
327
|
+
return this.ifNotLocked(() => this.chainCodeBuffer.toString('hex'))
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
get privateKeyBuffer() {
|
|
331
|
+
return this.ifNotLocked(() => this.hdnode.privateKey)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
get privateKey() {
|
|
335
|
+
return this.ifNotLocked(() => this.privateKeyBuffer.toString('hex'))
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
get publicKeyBuffer() {
|
|
339
|
+
return this.ifNotLocked(() => this.hdnode.publicKey)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
get publicKey() {
|
|
343
|
+
return this.ifNotLocked(() => this.publicKeyBuffer.toString('hex'))
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
async ethereumAddress() {
|
|
347
|
+
const address = await publicKeyToEthereumAddress(this.publicKeyBuffer);
|
|
348
|
+
return address
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
get leofcoinAddress() {
|
|
352
|
+
return bs58Check__default["default"].encode(this.neutered.publicKeyBuffer)
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
get address() {
|
|
356
|
+
return this.getAddressForCoin()
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async getAddressForCoin(coin_type) {
|
|
360
|
+
if (!coin_type) coin_type = this.hdnode.network.coin_type;
|
|
361
|
+
if (coin_type === 1) {
|
|
362
|
+
if (this.networkName?.split(':')[0] === 'ethereum') coin_type = 60;
|
|
363
|
+
if (this.networkName?.split(':')[0] === 'leofcoin') coin_type = 640;
|
|
364
|
+
}
|
|
365
|
+
// if (coin_type === 0) return this.bitcoinAddress
|
|
366
|
+
if (coin_type === 60) return this.ethereumAddress()
|
|
367
|
+
if (coin_type === 640) return this.leofcoinAddress
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
get accountAddress() {
|
|
371
|
+
return this.ifNotLocked(() => bs58Check__default["default"].encode(this.hdnode.publicKeyBuffer))
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
get isTestnet() {
|
|
375
|
+
if (typeof network === 'string')
|
|
376
|
+
this.hdnode.network = fromNetworkString(network);
|
|
377
|
+
|
|
378
|
+
return Boolean(this.hdnode.network.coin_type === 1)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
constructor(network, hdnode) {
|
|
382
|
+
if (typeof network === 'string') {
|
|
383
|
+
this.networkName = network;
|
|
384
|
+
this.network = fromNetworkString(network);
|
|
385
|
+
} else if (typeof network === 'object')
|
|
386
|
+
this.network = network;
|
|
387
|
+
|
|
388
|
+
if (hdnode) this.defineHDNode(hdnode);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
ifNotLocked(fn, params) {
|
|
392
|
+
if (!this.locked) return fn(params);
|
|
393
|
+
return null
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
defineHDNode(value) {
|
|
397
|
+
Object.defineProperty(this, 'hdnode', {
|
|
398
|
+
configurable: false,
|
|
399
|
+
writable: false,
|
|
400
|
+
value: value
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
validateNetwork(network) {
|
|
405
|
+
if (!network && !this.network) return console.error(`expected network to be defined`);
|
|
406
|
+
if (!network && this.network) network = this.network;
|
|
407
|
+
if (typeof network === 'string') network = fromNetworkString(network);
|
|
408
|
+
if (typeof network !== 'object') return console.error('network not found');
|
|
409
|
+
return network;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
async generate(password, network) {
|
|
413
|
+
network = this.validateNetwork(network);
|
|
414
|
+
const mnemonic = await new Mnemonic().generate(512);
|
|
415
|
+
const seed = await new Mnemonic().seedFromMnemonic(mnemonic, password, 512);
|
|
416
|
+
this.defineHDNode(bip32__namespace.fromSeed(Buffer.from(seed, 'arrayBuffer'), network));
|
|
417
|
+
return mnemonic;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* recover using mnemonic (recovery word list)
|
|
422
|
+
*/
|
|
423
|
+
async recover(mnemonic, password, network) {
|
|
424
|
+
network = this.validateNetwork(network, password);
|
|
425
|
+
const seed = await new Mnemonic().seedFromMnemonic(mnemonic, password, 512);
|
|
426
|
+
this.defineHDNode(bip32__namespace.fromSeed(Buffer.from(seed, 'arrayBuffer'), network));
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
load(base58, network) {
|
|
430
|
+
network = this.validateNetwork(network);
|
|
431
|
+
this.defineHDNode(bip32__namespace.fromBase58(base58, network));
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
save() {
|
|
435
|
+
return this.hdnode.toBase58();
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
fromAddress(address, chainCode, network) {
|
|
439
|
+
network = this.validateNetwork(network);
|
|
440
|
+
// if (network.coin_type === 60) {
|
|
441
|
+
// address = Buffer.from(address, 'hex')
|
|
442
|
+
// } else {
|
|
443
|
+
address = bs58Check__default["default"].decode(address);
|
|
444
|
+
// }
|
|
445
|
+
|
|
446
|
+
if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = address.slice(1);
|
|
447
|
+
this.defineHDNode(bip32__namespace.fromPublicKey(address, chainCode, network));
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
fromPublicKey(hex, chainCode, network) {
|
|
451
|
+
network = this.validateNetwork(network);
|
|
452
|
+
if (!Buffer.isBuffer(hex)) hex = Buffer.from(hex, 'hex');
|
|
453
|
+
if (!chainCode || chainCode && !Buffer.isBuffer(chainCode)) chainCode = hex.slice(1);
|
|
454
|
+
this.defineHDNode(bip32__namespace.fromPublicKey(hex, chainCode, network));
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
const { ecdsaSign, ecdsaVerify } = secp256k1__default["default"];
|
|
459
|
+
class MultiSignature {
|
|
460
|
+
multiCodec;
|
|
461
|
+
version;
|
|
462
|
+
decoded;
|
|
463
|
+
encoded;
|
|
464
|
+
#multiSignature;
|
|
465
|
+
constructor(version, multiCodec) {
|
|
466
|
+
if (version === undefined)
|
|
467
|
+
throw ReferenceError('version undefined');
|
|
468
|
+
if (multiCodec === undefined)
|
|
469
|
+
throw ReferenceError('multicodec undefined');
|
|
470
|
+
this.multiCodec = multiCodec;
|
|
471
|
+
this.version = version;
|
|
472
|
+
}
|
|
473
|
+
set multiSignature(value) {
|
|
474
|
+
this.#multiSignature = value;
|
|
475
|
+
}
|
|
476
|
+
get signature() {
|
|
477
|
+
return this.decoded.signature;
|
|
478
|
+
}
|
|
479
|
+
get multiSignature() {
|
|
480
|
+
return this.#multiSignature || this.encoded || this.encode(this.signature);
|
|
481
|
+
}
|
|
482
|
+
export() {
|
|
483
|
+
return base58__default["default"].encode(this.multiSignature);
|
|
484
|
+
}
|
|
485
|
+
import(encoded) {
|
|
486
|
+
return base58__default["default"].decode(encoded);
|
|
487
|
+
}
|
|
488
|
+
sign(hash, privateKey) {
|
|
489
|
+
if (!hash || !privateKey)
|
|
490
|
+
throw ReferenceError(`${hash ? 'privateKey' : 'hash'} undefined`);
|
|
491
|
+
const { signature } = ecdsaSign(hash, privateKey);
|
|
492
|
+
this.decoded = {
|
|
493
|
+
version: this.version,
|
|
494
|
+
multiCodec: this.multiCodec,
|
|
495
|
+
signature
|
|
496
|
+
};
|
|
497
|
+
return this.encode(signature);
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* verify signature (multiSignature.signature)
|
|
501
|
+
*/
|
|
502
|
+
verifySignature(signature, hash, publicKey) {
|
|
503
|
+
return ecdsaVerify(signature, hash, publicKey);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* verify multiSignature
|
|
507
|
+
*/
|
|
508
|
+
verify(multiSignature, hash, publicKey) {
|
|
509
|
+
multiSignature = this.decode(multiSignature);
|
|
510
|
+
return ecdsaVerify(multiSignature.signature, hash, publicKey);
|
|
511
|
+
}
|
|
512
|
+
encode(signature) {
|
|
513
|
+
signature = signature || this.signature;
|
|
514
|
+
if (!signature)
|
|
515
|
+
throw ReferenceError('signature undefined');
|
|
516
|
+
const encodedVersion = varint__default["default"].encode(this.version);
|
|
517
|
+
const encodedCodec = varint__default["default"].encode(this.multiCodec);
|
|
518
|
+
const uint8Array = new Uint8Array(encodedVersion.length + encodedCodec.length + signature.length);
|
|
519
|
+
uint8Array.set(encodedVersion);
|
|
520
|
+
uint8Array.set(encodedCodec, encodedVersion.length);
|
|
521
|
+
uint8Array.set(signature, encodedVersion.length + encodedCodec.length);
|
|
522
|
+
this.multiSignature = uint8Array;
|
|
523
|
+
return this.multiSignature;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* decode exported multi signature to object
|
|
527
|
+
* @param {multiSignature} multiSignature base58 encoded string
|
|
528
|
+
* @return {decodedMultiSignature} { version, multiCodec, signature }
|
|
529
|
+
*/
|
|
530
|
+
decode(multiSignature) {
|
|
531
|
+
if (multiSignature)
|
|
532
|
+
this.multiSignature = multiSignature;
|
|
533
|
+
if (!this.multiSignature)
|
|
534
|
+
throw ReferenceError('multiSignature undefined');
|
|
535
|
+
let buffer = this.multiSignature;
|
|
536
|
+
const version = varint__default["default"].decode(buffer);
|
|
537
|
+
buffer = buffer.slice(varint__default["default"].decode.bytes);
|
|
538
|
+
const codec = varint__default["default"].decode(buffer);
|
|
539
|
+
const signature = buffer.slice(varint__default["default"].decode.bytes);
|
|
540
|
+
if (version !== this.version)
|
|
541
|
+
throw TypeError('Invalid version');
|
|
542
|
+
if (this.multiCodec !== codec)
|
|
543
|
+
throw TypeError('Invalid multiCodec');
|
|
544
|
+
this.decoded = {
|
|
545
|
+
version,
|
|
546
|
+
multiCodec: codec,
|
|
547
|
+
signature
|
|
548
|
+
};
|
|
549
|
+
return this.decoded;
|
|
550
|
+
}
|
|
551
|
+
toHex() {
|
|
552
|
+
return this.multiSignature.toString('hex');
|
|
553
|
+
}
|
|
554
|
+
fromHex(hex) {
|
|
555
|
+
return base58__default["default"].decode(hex);
|
|
556
|
+
}
|
|
557
|
+
toBs58() {
|
|
558
|
+
return base58__default["default"].encode(this.multiSignature);
|
|
559
|
+
}
|
|
560
|
+
fromBs58(multiSignature) {
|
|
561
|
+
return base58__default["default"].decode(multiSignature);
|
|
562
|
+
}
|
|
563
|
+
toBs32() {
|
|
564
|
+
return base32__default["default"].encode(this.multiSignature);
|
|
565
|
+
}
|
|
566
|
+
fromBs32(multiSignature) {
|
|
567
|
+
return base32__default["default"].decode(multiSignature);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
// TODO: multihash addresses
|
|
572
|
+
class HDAccount {
|
|
573
|
+
/**
|
|
574
|
+
* @param {number} depth - acount depth
|
|
575
|
+
*/
|
|
576
|
+
constructor(node, depth = 0) {
|
|
577
|
+
this.node = node;
|
|
578
|
+
this.depth = depth;
|
|
579
|
+
this._prefix = `m/44'/${node.network.coin_type}'/${depth}'/`;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* @param {number} index - address index
|
|
584
|
+
*/
|
|
585
|
+
internal(index = 0) {
|
|
586
|
+
return this.node.derivePath(`${this._prefix}1/${index}`)
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* @param {number} index - address index
|
|
591
|
+
*/
|
|
592
|
+
external(index = 0) {
|
|
593
|
+
return this.node.derivePath(`${this._prefix}0/${index}`)
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
class MultiWallet extends HDWallet {
|
|
598
|
+
constructor(network, hdnode) {
|
|
599
|
+
super(network, hdnode);
|
|
600
|
+
this.multiCodec = this.network.multiCodec;
|
|
601
|
+
this.version = 0x00;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
get id() {
|
|
605
|
+
const buffer = Buffer.concat([
|
|
606
|
+
Buffer.from(varint__default["default"].encode(this.multiCodec)),
|
|
607
|
+
Buffer.from(this.account(0).node.neutered.publicKey, 'hex')
|
|
608
|
+
]);
|
|
609
|
+
return bs58Check__default["default"].encode(buffer)
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
get multiWIF() {
|
|
613
|
+
return this.ifNotLocked(() => this.encode())
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
get neutered() {
|
|
617
|
+
const neutered = this.ifNotLocked(() => new MultiWallet(this.networkName, this.hdnode.neutered()));
|
|
618
|
+
if (neutered) this._neutered = neutered;
|
|
619
|
+
return this._neutered
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
fromId(id) {
|
|
623
|
+
let buffer = bs58Check__default["default"].decode(id);
|
|
624
|
+
varint__default["default"].decode(buffer);
|
|
625
|
+
buffer = buffer.slice(varint__default["default"].decode.bytes);
|
|
626
|
+
this.fromPublicKey(buffer, null, this.networkName);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
async lock(multiWIF) {
|
|
630
|
+
if (!multiWIF) multiWIF = this.multiWIF;
|
|
631
|
+
this.encrypted = await encrypt(multiWIF.toString('hex'));
|
|
632
|
+
this.locked = true;
|
|
633
|
+
return this.encrypted
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
async unlock({key, iv, cipher}) {
|
|
637
|
+
const decrypted = await decrypt(cipher, key, iv);
|
|
638
|
+
this.import(decrypted);
|
|
639
|
+
this.locked = false;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
export() {
|
|
643
|
+
return this.encode();
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* encodes the multiWIF and loads wallet from bs58
|
|
648
|
+
*
|
|
649
|
+
* @param {multiWIF} multiWIF - note a multiWIF is not the same as a wif
|
|
650
|
+
*/
|
|
651
|
+
import(multiWIF) {
|
|
652
|
+
const { bs58, version, multiCodec } = this.decode(multiWIF);
|
|
653
|
+
this.network = Object.values(networks).reduce((p, c) => {
|
|
654
|
+
if (c.multiCodec===multiCodec) return c
|
|
655
|
+
else if (c.testnet && c.testnet.multiCodec === multiCodec) return c.testnet
|
|
656
|
+
else return p
|
|
657
|
+
}, networks['leofcoin']);
|
|
658
|
+
this.load(bs58, this.networkName);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* @return base58Check encoded string
|
|
663
|
+
*/
|
|
664
|
+
encode() {
|
|
665
|
+
const buffer = Buffer.concat([
|
|
666
|
+
Buffer.from(varint__default["default"].encode(this.version)),
|
|
667
|
+
Buffer.from(varint__default["default"].encode(this.multiCodec)),
|
|
668
|
+
bs58Check__default["default"].decode(this.save())
|
|
669
|
+
]);
|
|
670
|
+
return bs58Check__default["default"].encode(buffer);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
decode(bs58) {
|
|
674
|
+
let buffer = bs58Check__default["default"].decode(bs58);
|
|
675
|
+
const version = varint__default["default"].decode(buffer);
|
|
676
|
+
buffer = buffer.slice(varint__default["default"].decode.bytes);
|
|
677
|
+
const multiCodec = varint__default["default"].decode(buffer);
|
|
678
|
+
buffer = buffer.slice(varint__default["default"].decode.bytes);
|
|
679
|
+
bs58 = bs58Check__default["default"].encode(buffer);
|
|
680
|
+
if (version !== this.version) throw TypeError('Invalid version');
|
|
681
|
+
if (this.multiCodec !== multiCodec) throw TypeError('Invalid multiCodec');
|
|
682
|
+
return { version, multiCodec, bs58 };
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
sign(hash) {
|
|
686
|
+
return new MultiSignature(this.version, this.network.multiCodec)
|
|
687
|
+
.sign(hash, this.privateKeyBuffer);
|
|
688
|
+
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
verify(multiSignature, hash) {
|
|
692
|
+
return new MultiSignature(this.version, this.network.multiCodec)
|
|
693
|
+
.verify(multiSignature, hash, this.publicKeyBuffer)
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* @param {number} account - account to return chain for
|
|
698
|
+
* @return { internal(addressIndex), external(addressIndex) }
|
|
699
|
+
*/
|
|
700
|
+
account(index) {
|
|
701
|
+
return new HDAccount(new MultiWallet(this.networkName, this.hdnode), index);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* m / purpose' / coin_type' / account' / change / aadress_index
|
|
706
|
+
*
|
|
707
|
+
* see https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
|
|
708
|
+
*/
|
|
709
|
+
derivePath(path) {
|
|
710
|
+
return new MultiWallet(this.networkName, this.hdnode.derivePath(path))
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
derive(index) {
|
|
714
|
+
return new MultiWallet(this.networkName, this.hdnode.derive(index));
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
exports["default"] = MultiWallet;
|