nis-ruby 0.0.11.1 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/LICENSE +21 -0
  4. data/README.md +23 -43
  5. data/{samples/request_account.rb → examples/account.rb} +2 -10
  6. data/{samples/request_block.rb → examples/block.rb} +0 -0
  7. data/{samples/request_debug.rb → examples/debug.rb} +0 -8
  8. data/{samples/request_local.rb → examples/local.rb} +0 -5
  9. data/{samples/request_namespace.rb → examples/namespace.rb} +0 -3
  10. data/{samples/request_nis.rb → examples/nis.rb} +0 -0
  11. data/{samples/request_node.rb → examples/node.rb} +0 -9
  12. data/examples/shutdown.rb +6 -0
  13. data/examples/transactions/importance_transfer.rb +22 -0
  14. data/examples/transactions/mosaic_definition_creation.rb +50 -0
  15. data/examples/transactions/mosaic_supply_change.rb +24 -0
  16. data/examples/transactions/multisig.rb +26 -0
  17. data/examples/transactions/multisig_add_cosignatory.rb +31 -0
  18. data/examples/transactions/multisig_aggregate_modification.rb +28 -0
  19. data/examples/transactions/multisig_signature.rb +38 -0
  20. data/examples/transactions/provision_namespace.rb +19 -0
  21. data/examples/transactions/transfer.rb +22 -0
  22. data/lib/nis.rb +8 -4
  23. data/lib/nis/client.rb +2 -1
  24. data/lib/nis/endpoint/shutdown.rb +7 -0
  25. data/lib/nis/endpoint/transaction/announce.rb +1 -1
  26. data/lib/nis/endpoint/transaction/prepareAnnounce.rb +1 -1
  27. data/lib/nis/fee.rb +1 -0
  28. data/lib/nis/fee/importance_transfer.rb +22 -0
  29. data/lib/nis/fee/mosaic_definition_creation.rb +22 -0
  30. data/lib/nis/fee/mosaic_supply_change_transfer.rb +22 -0
  31. data/lib/nis/fee/multisig.rb +22 -0
  32. data/lib/nis/fee/multisig_aggregation_modification.rb +30 -0
  33. data/lib/nis/fee/provision_namespace.rb +32 -0
  34. data/lib/nis/fee/transfer.rb +51 -0
  35. data/lib/nis/keypair.rb +18 -0
  36. data/lib/nis/mixin/struct.rb +50 -0
  37. data/lib/nis/request.rb +1 -0
  38. data/lib/nis/request/announce.rb +10 -0
  39. data/lib/nis/request/prepare_announce.rb +48 -0
  40. data/lib/nis/struct/block.rb +1 -1
  41. data/lib/nis/struct/mosaic_properties.rb +2 -2
  42. data/lib/nis/transaction/importance_transfer.rb +25 -28
  43. data/lib/nis/transaction/mosaic_definition_creation.rb +33 -34
  44. data/lib/nis/transaction/mosaic_supply_change.rb +30 -30
  45. data/lib/nis/transaction/multisig.rb +17 -36
  46. data/lib/nis/transaction/multisig_aggregate_modification.rb +29 -31
  47. data/lib/nis/transaction/multisig_signature.rb +24 -23
  48. data/lib/nis/transaction/provision_namespace.rb +53 -33
  49. data/lib/nis/transaction/transfer.rb +22 -52
  50. data/lib/nis/util.rb +16 -13
  51. data/lib/nis/version.rb +1 -1
  52. data/nis.gemspec +2 -0
  53. metadata +62 -19
  54. data/lib/nis/mixin/network.rb +0 -20
  55. data/samples/request_importance_transfer_transaction.rb +0 -34
  56. data/samples/request_mosaic_definition_creation_transaction.rb +0 -62
  57. data/samples/request_mosaic_supply_change_transaction.rb +0 -35
  58. data/samples/request_multisig_add_cosignatory_transaction.rb +0 -58
  59. data/samples/request_multisig_aggregate_modification_transaction.rb +0 -45
  60. data/samples/request_multisig_signature_transaction.rb +0 -53
  61. data/samples/request_multisig_transaction.rb +0 -54
  62. data/samples/request_provision_namespace_transaction.rb +0 -31
  63. data/samples/request_transfer_transaction.rb +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b71820d8d2ab72e1c4ddc2777939b2099a2ff716
4
- data.tar.gz: 7bf8eef6eeed3ead69f68e40d3ffa1c63d8f3077
3
+ metadata.gz: 48fc594828a7e878a2d93c176aa7969eda269b74
4
+ data.tar.gz: dfa004cc7326b9cc581cc5e42e32fa4e6cbc7117
5
5
  SHA512:
6
- metadata.gz: 891cdec923af05c61c85c9af8aa644cd2fb5ed5508bea4505ce5ebd5a93896706c91f502518079fd7da8494c02d8c4fb4819446c52e4d8b9115eafab84a3787f
7
- data.tar.gz: af8eb1fa70b6d3e5b098b31e5969904598ff72956748d3f70e3e1dc496f8e49164a8bc3201839cbe38639a74b54a33f3d785f036e44ff6d405cdc1124219c21a
6
+ metadata.gz: 5e0b204992ea6daabbb0186484d98978a984e28598f6bb0bbd4f891143d97292c118c57993be1db835b51790649bbcd6b69c3f98a22934afb9ecd9e52c64ba12
7
+ data.tar.gz: dcfcace177ac5abcb30c0f90dcb83f62e4586c3a73a343d098de82b5dc9d5aadb968765a4e7628b2fa647d7aca5488eb652c6c5c3c1bdbd83b9309789ec19144
data/.travis.yml CHANGED
@@ -3,7 +3,7 @@ language: ruby
3
3
  rvm:
4
4
  - 2.4.0
5
5
  - 2.3.0
6
- - 2.2.0
6
+ - 2.2.6
7
7
 
8
8
  branches:
9
9
  only:
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Yoshiyuki Ieyama
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -26,10 +26,9 @@ Or add this line to your application's Gemfile:
26
26
  gem 'nis-ruby'
27
27
  ```
28
28
 
29
-
30
29
  ## Usage
31
30
 
32
- More specific sample codes are in **samples/** directory.
31
+ More specific example codes are in **examples/** directory.
33
32
 
34
33
  ### Methods
35
34
 
@@ -44,22 +43,16 @@ nis.status
44
43
  # => {code: 6, type: 4, message: "status"}
45
44
  # See http://bob.nem.ninja/docs/#status-request
46
45
 
46
+ kp = Nis::Keypair.new(SENDER_PRIV_KEY)
47
47
  tx = Nis::Transaction::Transfer.new(
48
- amount: 10_000_000,
49
- recipient: RECIPIENT_ADDRESS,
50
- signer: SENDER_PUBLIC_KEY,
51
- message: Nis::Struct::Message.new('Hello'),
52
- timeStamp: Nis::Util.timestamp,
53
- deadline: Nis::Util.timestamp + 43_200,
54
- version: Nis::Util::TESTNET_VERSION_1
55
- )
56
-
57
- rpa = Nis::Struct::RequestPrepareAnnounce.new(
58
- transaction: tx,
59
- privateKey: SENDER_PRIVATE_KEY
48
+ RECIPIENT_ADDRESS,
49
+ 10_000_000,
50
+ 'Message'
60
51
  )
61
-
62
- nis.transaction_prepare_announce(request_prepare_announce: rpa)
52
+ req = Nis::Request::PrepareAnnounce.new(tx, kp)
53
+ nis.transaction_prepare_announce(req)
54
+ # See http://bob.nem.ninja/docs/#initiating-a-transfer-transaction
55
+ # => {innerTransactionHash: {}, code: 1, type: 1, message: "SUCCESS", transactionHash: {data: "9da41fd6c6886740ae6a15c869df0470015d78103e5b216971aa09fdbcce9cde"}}
63
56
  ```
64
57
 
65
58
  ### Requesting
@@ -78,27 +71,6 @@ nis.request(:post, '/account/unlock',
78
71
  )
79
72
  # => Nothing
80
73
  # See http://bob.nem.ninja/docs/#locking-and-unlocking-accounts
81
-
82
- tx = {
83
- amount: 10_000_000,
84
- fee: 1_000_000,
85
- recipient: 'TALICELCD3XPH4FFI5STGGNSNSWPOTG5E4DS2TOS',
86
- signer: 'a1aaca6c17a24252e674d155713cdf55996ad00175be4af02a20c67b59f9fe8a',
87
- message: {
88
- payload: '',
89
- type: 1
90
- },
91
- type: 0x0101, # 257
92
- timeStamp: Nis::Util.timestamp,
93
- deadline: Nis::Util.timestamp + 43_200,
94
- version: Nis::Util::TESTNET_VERSION_1
95
- }
96
- puts nis.request! :post, 'transaction/prepare-announce', {
97
- transaction: tx,
98
- privateKey: '68e4f79f886927de698df4f857de2aada41ccca6617e56bb0d61623b35b08cc0'
99
- }
100
- # => {innerTransactionHash: {}, code: 1, type: 1, message: "SUCCESS", transactionHash: {data: "9da41fd6c6886740ae6a15c869df0470015d78103e5b216971aa09fdbcce9cde"}}
101
- # See http://bob.nem.ninja/docs/#initiating-a-transfer-transaction
102
74
  ```
103
75
 
104
76
 
@@ -121,12 +93,10 @@ $ nis request get account/harvests --params=address:TALICELCD3XPH4FFI5STGGNSNSWP
121
93
 
122
94
  ## Connection
123
95
 
124
- ### Environment Variable
96
+ You can find nodes here.
97
+ - [NEM Node Rewards](https://supernodes.nem.io/)
125
98
 
126
- ```bash
127
- $ export NIS_URL=http://bigalice3.nem.ninja:7890
128
- $ nis heartbeat # => {"code":1,"type":2,"message":"ok"}
129
- ```
99
+ *Currently the gem only supports transactions for local node.*
130
100
 
131
101
  ### Hash
132
102
 
@@ -138,13 +108,23 @@ Nis.new(host: 'bigalice3.nem.ninja')
138
108
  Nis.new(url: 'http://bigalice3.nem.ninja:7890')
139
109
  ```
140
110
 
111
+ ### Environment Variable
112
+
113
+ ```bash
114
+ $ export NIS_URL=http://bigalice3.nem.ninja:7890
115
+ $ nis heartbeat # => {"code":1,"type":2,"message":"ok"}
116
+ ```
117
+
118
+ Environment variable used as default value.
119
+
141
120
 
142
121
  ## TODO
143
122
 
144
123
  * Do more improvements
124
+ * Remote transaction
145
125
  * Mosaic transferring
146
126
  * Encryption message
147
- * Remote transaction
127
+ * Be more easy to use
148
128
 
149
129
 
150
130
  ## Documentation
@@ -1,5 +1,4 @@
1
1
  require 'nis'
2
- hr = '-' * 64
3
2
 
4
3
  # create NIS instance
5
4
  nis = Nis.new
@@ -9,44 +8,37 @@ nis = Nis.new
9
8
  # Each endpoint mapped into method name.
10
9
  # It returns Nis::Struct object which mapped API response.
11
10
  keypair = nis.account_generate
12
- puts hr
13
11
 
14
12
  # Access properties.
15
13
  # Names are same API response.
16
14
  puts keypair.address
17
15
  puts keypair.privateKey
18
16
  puts keypair.publicKey
19
- puts hr
20
17
 
21
18
  # Ruby style access.
22
19
  # Also can be access property by snakecase.
23
20
  puts keypair.private_key
24
21
  puts keypair.public_key
25
- puts hr
26
22
 
27
23
  # hash like access.
28
24
  # Also can be access property like hash.
29
25
  puts keypair[:privateKey]
30
26
  puts keypair[:private_key]
31
- puts hr
32
27
 
33
28
  # Address object
34
29
  # Some property wrapped by value object.
35
30
  puts address = keypair.address
36
31
  puts address.testnet?
37
- puts hr
38
32
 
39
33
  # /account/get?address={address}
40
34
  # -> account_get address: {address}
41
35
  # Passing parameters by keyword arguments.
42
- account_meta_pair = nis.account_get address: keypair.address
36
+ account_meta_pair = nis.account_get(address: keypair.address)
43
37
  account = account_meta_pair[:account]
44
38
  puts account.balance
45
- puts hr
46
39
 
47
40
  # /account/get/from-public-key?public-key={key}
48
41
  # -> account_get_public_key public_key: {key}
49
- account_meta_pair = nis.account_get_from_public_key public_key: keypair.public_key
42
+ account_meta_pair = nis.account_get_from_public_key(public_key: keypair.public_key)
50
43
  account = account_meta_pair.account
51
44
  puts account.address
52
- puts hr
File without changes
@@ -1,6 +1,4 @@
1
- require 'pp'
2
1
  require 'nis'
3
- hr = '-' * 64
4
2
 
5
3
  nis = Nis.new
6
4
 
@@ -9,33 +7,27 @@ incoming = nis.debug_connections_incoming
9
7
  incoming[:outstanding].each do |ai|
10
8
  puts ai.to_hash
11
9
  end
12
- puts hr
13
10
 
14
11
  incoming[:most_recent].each do |ai|
15
12
  puts ai.to_hash
16
13
  end
17
- puts hr
18
14
 
19
15
  outgoing = nis.debug_connections_outgoing
20
16
 
21
17
  outgoing[:outstanding].each do |ai|
22
18
  puts ai.to_hash
23
19
  end
24
- puts hr
25
20
 
26
21
  outgoing[:most_recent].each do |ai|
27
22
  puts ai.to_hash
28
23
  end
29
- puts hr
30
24
 
31
25
  timers = nis.debug_connections_timers
32
26
  timers.each do |t|
33
27
  puts t.to_hash
34
28
  end
35
- puts hr
36
29
 
37
30
  syncs = nis.debug_time_synchronization
38
31
  syncs.each do |sync|
39
32
  puts sync.to_hash
40
33
  end
41
- puts hr
@@ -1,5 +1,4 @@
1
1
  require 'nis'
2
- hr = '-' * 64
3
2
 
4
3
  nis = Nis.new
5
4
 
@@ -9,16 +8,12 @@ page = Nis::Struct::AccountPrivateKeyTransactionsPage.new(
9
8
 
10
9
  incoming = nis.local_account_transfers_incoming(page: page)
11
10
  puts incoming.last.to_hash
12
- puts hr
13
11
 
14
12
  outgoing = nis.local_account_transfers_outgoing(page: page)
15
13
  puts outgoing.last.to_hash
16
- puts hr
17
14
 
18
15
  all = nis.local_account_transfers_all(page: page)
19
16
  puts all.last.to_hash
20
- puts hr
21
17
 
22
18
  blocks = nis.local_chain_blocks_after(block_height: 2649)
23
19
  puts blocks.last
24
- puts hr
@@ -1,12 +1,9 @@
1
1
  require 'nis'
2
- hr = '-' * 64
3
2
 
4
3
  nis = Nis.new
5
4
 
6
5
  ns_mosaics = nis.namespace_mosaic_definition_page(namespace: 'alice.misc')
7
6
  puts ns_mosaics.first.to_hash
8
- puts hr
9
7
 
10
8
  ns_root = nis.namespace_root_page
11
9
  puts ns_root.first.to_hash
12
- puts hr
File without changes
@@ -1,34 +1,26 @@
1
1
  require 'nis'
2
- hr = '-' * 64
3
2
 
4
3
  nis = Nis.new
5
4
 
6
5
  node_info = nis.node_info
7
6
  puts node_info.to_hash
8
- puts hr
9
7
 
10
8
  ext_node_info = nis.node_extended_info
11
9
  puts ext_node_info.to_hash
12
- puts hr
13
10
 
14
11
  node_exp = nis.node_experiences
15
12
  puts node_exp.first.to_hash
16
- puts hr
17
13
 
18
14
  peer_all = nis.node_peerlist_all
19
15
  puts peer_all.to_hash
20
- puts hr
21
16
 
22
17
  reachables = nis.node_peerlist_reachable
23
18
  puts reachables.first.to_hash
24
- puts hr
25
19
 
26
20
  actives = nis.node_peerlist_active
27
21
  puts actives.first.to_hash
28
- puts hr
29
22
 
30
23
  puts nis.node_active_peers_max_chain_height
31
- puts hr
32
24
 
33
25
  bnr = Nis::Struct::BootNodeRequest.new(
34
26
  metaData: {
@@ -50,4 +42,3 @@ begin
50
42
  rescue => ex
51
43
  puts ex
52
44
  end
53
- puts hr
@@ -0,0 +1,6 @@
1
+ require 'nis'
2
+
3
+ nis = Nis.new(host: 'localhost')
4
+
5
+ # only accept local node
6
+ nis.shutdown
@@ -0,0 +1,22 @@
1
+ require 'nis'
2
+
3
+ # sender
4
+ A_PRIVATE_KEY = '260206d683962350532408e8774fd14870a173b7fba17f6b504da3dbc5f1cc9f'
5
+ A_PUBLIC_KEY = 'cc63b4dcdec745417043c3fa0992ec3a1695461a26d90264744648abbd5caa0d'
6
+
7
+ # remote
8
+ B_PUBLIC_KEY = 'cc6c9485d15b992501e57fe3799487e99de272f79c5442de94eeb998b45e0144'
9
+
10
+ # TODO: public key calculated from private key in future version.
11
+ # it will not need to set public key.
12
+ kp = Nis::Keypair.new(A_PRIVATE_KEY, public_key: A_PUBLIC_KEY)
13
+
14
+ tx = Nis::Transaction::ImportanceTransfer.new(B_PUBLIC_KEY, :activate)
15
+ puts "Fee: #{tx.fee.to_i}"
16
+
17
+ nis = Nis.new
18
+ req = Nis::Request::PrepareAnnounce.new(tx, kp)
19
+ res = nis.transaction_prepare_announce(req)
20
+
21
+ puts "Message: #{res.message}"
22
+ puts "TransactionHash: #{res.transaction_hash}"
@@ -0,0 +1,50 @@
1
+ require 'nis'
2
+
3
+ # owner
4
+ A_PRIVATE_KEY = '4ce5c8f9fce571db0d9ac1adf00b8d3ba0f078ed40835fd3d730a2f24b834214'
5
+ A_PUBLIC_KEY = 'be2ba9cb15a547110d511a4d43c0482fbb584d78781abac01fb053d18f4a0033'
6
+ A_ADDRESS = 'TDPP2C4XQLMESBMCYGWN4NRAJAKZEYRV75KGYSOB'
7
+
8
+ # TODO: public key calculated from private key in future version.
9
+ # it will not need to set public key.
10
+ kp = Nis::Keypair.new(A_PRIVATE_KEY, public_key: A_PUBLIC_KEY)
11
+
12
+ mosaic_id = Nis::Struct::MosaicId.new(
13
+ namespaceId: 'sushi',
14
+ name: 'maguro'
15
+ )
16
+
17
+ properties = Nis::Struct::MosaicProperties.new(
18
+ divisibility: 0,
19
+ initialSupply: 10_000,
20
+ supplyMutable: true,
21
+ transferable: true
22
+ )
23
+
24
+ levy = Nis::Struct::MosaicLevy.new(
25
+ type: 1,
26
+ recipient: A_ADDRESS,
27
+ mosaicId: {
28
+ namespaceId: 'nem',
29
+ name: 'xem'
30
+ },
31
+ fee: 1_000
32
+ )
33
+
34
+ definition = Nis::Struct::MosaicDefinition.new(
35
+ creator: A_PUBLIC_KEY,
36
+ id: mosaic_id,
37
+ description: 'Japanese Soul food SHUSHI.',
38
+ properties: properties,
39
+ levy: levy
40
+ )
41
+
42
+ tx = Nis::Transaction::MosaicDefinitionCreation.new(definition)
43
+ puts "Fee: #{tx.fee.to_i}"
44
+
45
+ nis = Nis.new
46
+ req = Nis::Request::PrepareAnnounce.new(tx, kp)
47
+ res = nis.transaction_prepare_announce(req)
48
+
49
+ puts "Message: #{res.message}"
50
+ puts "TransactionHash: #{res.transaction_hash}"
@@ -0,0 +1,24 @@
1
+ require 'nis'
2
+
3
+ # owner
4
+ A_PRIVATE_KEY = '4ce5c8f9fce571db0d9ac1adf00b8d3ba0f078ed40835fd3d730a2f24b834214'
5
+ A_PUBLIC_KEY = 'be2ba9cb15a547110d511a4d43c0482fbb584d78781abac01fb053d18f4a0033'
6
+
7
+ # TODO: public key calculated from private key in future version.
8
+ # it will not need to set public key.
9
+ kp = Nis::Keypair.new(A_PRIVATE_KEY, public_key: A_PUBLIC_KEY)
10
+
11
+ mosaic_id = Nis::Struct::MosaicId.new(
12
+ namespaceId: 'sushi',
13
+ name: 'maguro'
14
+ )
15
+
16
+ tx = Nis::Transaction::MosaicSupplyChange.new(mosaic_id, :increase, 1_000)
17
+ puts "Fee: #{tx.fee.to_i}"
18
+
19
+ nis = Nis.new
20
+ req = Nis::Request::PrepareAnnounce.new(tx, kp)
21
+ res = nis.transaction_prepare_announce(req)
22
+
23
+ puts "Message: #{res.message}"
24
+ puts "TransactionHash: #{res.transaction_hash}"
@@ -0,0 +1,26 @@
1
+ require 'nis'
2
+
3
+ # multisig
4
+ # A_PRIVATE_KEY = '9bf8e6fd1a178a3cce39840cda34f80f55fe075c15f48eefad8506f4a70c2b47'
5
+ A_PUBLIC_KEY = '4b26a75313b747985470977a085ae6f840a0b84ebd96ddf17f4a31a2b580d078'
6
+ # A_ADDRESS = 'TBAOYZS4FGY5XPQ5OD2VL3SY7GQ5FLH66GRCX5DL'
7
+
8
+ # cosignatory
9
+ B_PRIVATE_KEY = '260206d683962350532408e8774fd14870a173b7fba17f6b504da3dbc5f1cc9f'
10
+ B_PUBLIC_KEY = 'cc63b4dcdec745417043c3fa0992ec3a1695461a26d90264744648abbd5caa0d'
11
+ B_ADDRESS = 'TAWKJTUP4DWKLDKKS534TYP6G324CBNMXKBA4X7B'
12
+
13
+ # TODO: public key calculated from private key in future version.
14
+ # it will not need to set public key.
15
+ kp = Nis::Keypair.new(B_PRIVATE_KEY, public_key: B_PUBLIC_KEY)
16
+
17
+ ttx = Nis::Transaction::Transfer.new(B_ADDRESS, 1_000_000, 'Good luck!')
18
+ tx = Nis::Transaction::Multisig.new(ttx, A_PUBLIC_KEY)
19
+ puts "Fee: #{tx.fee.to_i}"
20
+
21
+ nis = Nis.new
22
+ req = Nis::Request::PrepareAnnounce.new(tx, kp)
23
+ res = nis.transaction_prepare_announce(req)
24
+
25
+ puts "Message: #{res.message}"
26
+ puts "TransactionHash: #{res.transaction_hash}"