@@ -14,11 +14,11 @@ const secp256k1 = require('secp256k1');
14
14
const crypto = require ( 'crypto' ) ;
15
15
const bitcoinjs = require ( 'bitcoinjs-lib' ) ;
16
16
17
- const PATH = "m/44'/118'/0'/0/0" ;
18
-
19
- let Cosmos = function ( url , chainId ) {
17
+ let Cosmos = function ( url , chainId ) {
20
18
this . url = url ;
21
19
this . chainId = chainId ;
20
+ this . path = "m/44'/118'/0'/0/0" ;
21
+ this . bech32MainPrefix = "cosmos" ;
22
22
23
23
if ( ! this . url ) {
24
24
throw new Error ( "url object was not set or invalid" )
@@ -49,6 +49,34 @@ function getPubKeyBase64(ecpairPriv) {
49
49
return Buffer . from ( pubKeyByte , 'binary' ) . toString ( 'base64' ) ;
50
50
}
51
51
52
+ function sortObject ( obj ) {
53
+ if ( obj === null ) return null ;
54
+ if ( typeof obj !== "object" ) return obj ;
55
+ if ( Array . isArray ( obj ) ) return obj . map ( sortObject ) ;
56
+ const sortedKeys = Object . keys ( obj ) . sort ( ) ;
57
+ const result = { } ;
58
+ sortedKeys . forEach ( key => {
59
+ result [ key ] = sortObject ( obj [ key ] )
60
+ } ) ;
61
+ return result ;
62
+ }
63
+
64
+ Cosmos . prototype . setBech32MainPrefix = function ( bech32MainPrefix ) {
65
+ this . bech32MainPrefix = bech32MainPrefix ;
66
+
67
+ if ( ! this . bech32MainPrefix ) {
68
+ throw new Error ( "bech32MainPrefix object was not set or invalid" )
69
+ }
70
+ }
71
+
72
+ Cosmos . prototype . setPath = function ( path ) {
73
+ this . path = path ;
74
+
75
+ if ( ! this . path ) {
76
+ throw new Error ( "path object was not set or invalid" )
77
+ }
78
+ }
79
+
52
80
Cosmos . prototype . getAccounts = function ( address ) {
53
81
return fetch ( this . url + "/auth/accounts/" + address )
54
82
. then ( response => response . json ( ) )
@@ -60,9 +88,9 @@ Cosmos.prototype.getAddress = function(mnemonic) {
60
88
}
61
89
const seed = bip39 . mnemonicToSeed ( mnemonic ) ;
62
90
const node = bip32 . fromSeed ( seed ) ;
63
- const child = node . derivePath ( PATH ) ;
91
+ const child = node . derivePath ( this . path ) ;
64
92
const words = bech32 . toWords ( child . identifier ) ;
65
- return bech32 . encode ( 'cosmos' , words ) ;
93
+ return bech32 . encode ( this . bech32MainPrefix , words ) ;
66
94
}
67
95
68
96
Cosmos . prototype . getECPairPriv = function ( mnemonic ) {
@@ -71,7 +99,7 @@ Cosmos.prototype.getECPairPriv = function(mnemonic) {
71
99
}
72
100
const seed = bip39 . mnemonicToSeed ( mnemonic ) ;
73
101
const node = bip32 . fromSeed ( seed ) ;
74
- const child = node . derivePath ( PATH ) ;
102
+ const child = node . derivePath ( this . path ) ;
75
103
const ecpair = bitcoinjs . ECPair . fromPrivateKey ( child . privateKey , { compressed : false } )
76
104
return ecpair . privateKey ;
77
105
}
@@ -82,7 +110,7 @@ Cosmos.prototype.NewStdMsg = function(input) {
82
110
if ( input . type == "cosmos-sdk/MsgSend" ) {
83
111
stdSignMsg . json =
84
112
{
85
- account_number : String ( input . account_number ) ,
113
+ account_number : String ( input . account_number ) ,
86
114
chain_id : this . chainId ,
87
115
fee : {
88
116
amount : [
@@ -321,18 +349,44 @@ Cosmos.prototype.NewStdMsg = function(input) {
321
349
] ,
322
350
sequence : String ( input . sequence )
323
351
}
352
+ } else if ( input . type == "cosmos-sdk/MsgModifyWithdrawAddress" ) {
353
+ stdSignMsg . json =
354
+ {
355
+ account_number : String ( input . account_number ) ,
356
+ chain_id : this . chainId ,
357
+ fee : {
358
+ amount : [
359
+ {
360
+ amount : String ( input . fee ) ,
361
+ denom : input . feeDenom
362
+ }
363
+ ] ,
364
+ gas : String ( input . gas )
365
+ } ,
366
+ memo : input . memo ,
367
+ msgs : [
368
+ {
369
+ type : input . type ,
370
+ value : {
371
+ delegator_address : input . delegator_address ,
372
+ withdraw_address : input . withdraw_address
373
+ }
374
+ }
375
+ ] ,
376
+ sequence : String ( input . sequence )
377
+ }
324
378
} else {
325
379
throw new Error ( "No such input.type: " + input . type )
326
380
}
327
381
328
- stdSignMsg . bytes = convertStringToBytes ( JSON . stringify ( stdSignMsg . json ) ) ;
382
+ stdSignMsg . bytes = convertStringToBytes ( JSON . stringify ( sortObject ( stdSignMsg . json ) ) ) ;
329
383
330
384
return stdSignMsg ;
331
385
}
332
386
333
387
Cosmos . prototype . sign = function ( stdSignMsg , ecpairPriv , modeType = "sync" ) {
334
388
// The supported return types includes "block"(return after tx commit), "sync"(return afer CheckTx) and "async"(return right away).
335
- const hash = crypto . createHash ( 'sha256' ) . update ( JSON . stringify ( stdSignMsg . json ) ) . digest ( 'hex' ) ;
389
+ const hash = crypto . createHash ( 'sha256' ) . update ( JSON . stringify ( sortObject ( stdSignMsg . json ) ) ) . digest ( 'hex' ) ;
336
390
const buf = Buffer . from ( hash , 'hex' ) ;
337
391
let signObj = secp256k1 . sign ( buf , ecpairPriv ) ;
338
392
var signatureBase64 = Buffer . from ( signObj . signature , 'binary' ) . toString ( 'base64' ) ;
0 commit comments