appchain.rb 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.gitmodules +6 -0
- data/.pryrc +4 -0
- data/.rspec +3 -0
- data/.rubocop.yml +103 -0
- data/.travis.yml +16 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +95 -0
- data/LICENSE.txt +21 -0
- data/README.md +88 -0
- data/Rakefile +6 -0
- data/appchain.gemspec +47 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/appchain.rb +19 -0
- data/lib/appchain/address.rb +26 -0
- data/lib/appchain/client.rb +17 -0
- data/lib/appchain/contract.rb +98 -0
- data/lib/appchain/http.rb +57 -0
- data/lib/appchain/protos/blockchain_pb.rb +110 -0
- data/lib/appchain/rpc.rb +78 -0
- data/lib/appchain/transaction.rb +47 -0
- data/lib/appchain/transaction_signer.rb +79 -0
- data/lib/appchain/utils.rb +75 -0
- data/lib/appchain/version.rb +5 -0
- data/lib/web3_eth/contract.rb +28 -0
- metadata +226 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AppChain
|
4
|
+
class Transaction
|
5
|
+
attr_accessor :to, :nonce, :quota, :valid_until_block, :data, :value, :chain_id, :version
|
6
|
+
|
7
|
+
# @param nonce [String]
|
8
|
+
# @param valid_until_block [Integer]
|
9
|
+
# @param chain_id [Integer]
|
10
|
+
# @param version [Integer]
|
11
|
+
# @param to [String]
|
12
|
+
# @param data [String]
|
13
|
+
# @param value: [String | Integer] hex string or decimal integer
|
14
|
+
# @param quota [Integer]
|
15
|
+
#
|
16
|
+
# @return [void]
|
17
|
+
def initialize(nonce:, valid_until_block:, chain_id:, version: 0, to: nil, data: nil, value: "0", quota: 1_000_000)
|
18
|
+
@to = to
|
19
|
+
@nonce = nonce
|
20
|
+
@quota = quota
|
21
|
+
@valid_until_block = valid_until_block
|
22
|
+
@data = data
|
23
|
+
@chain_id = chain_id
|
24
|
+
@version = version
|
25
|
+
@value = if value.is_a?(Integer)
|
26
|
+
Utils.to_hex(value)
|
27
|
+
else
|
28
|
+
value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.from_hash(hash)
|
33
|
+
h = hash.map { |k, v| { k.to_sym => v } }.reduce({}, :merge)
|
34
|
+
|
35
|
+
new(
|
36
|
+
nonce: h[:nonce],
|
37
|
+
valid_until_block: h[:valid_until_block],
|
38
|
+
chain_id: h[:chain_id],
|
39
|
+
to: h[:to],
|
40
|
+
data: h[:data],
|
41
|
+
version: h[:version] || 0,
|
42
|
+
value: h[:value] || "0",
|
43
|
+
quota: h[:quota] || 1_000_000
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "ciri/utils"
|
4
|
+
require "ciri/crypto"
|
5
|
+
|
6
|
+
module AppChain
|
7
|
+
class TransactionSigner
|
8
|
+
class << self
|
9
|
+
# sign transaction
|
10
|
+
#
|
11
|
+
# @param transaction [AppChain::Transaction]
|
12
|
+
# @param private_key [String]
|
13
|
+
def encode(transaction, private_key)
|
14
|
+
tx = AppChain::Protos::Transaction.new
|
15
|
+
|
16
|
+
tx.nonce = transaction.nonce
|
17
|
+
to = AppChain::Utils.remove_hex_prefix(transaction.to)&.downcase
|
18
|
+
tx.to = to unless to.nil?
|
19
|
+
tx.quota = transaction.quota
|
20
|
+
tx.data = AppChain::Utils.to_bytes(transaction.data)
|
21
|
+
tx.version = transaction.version
|
22
|
+
tx.value = process_value(transaction.value)
|
23
|
+
tx.chain_id = transaction.chain_id
|
24
|
+
tx.valid_until_block = transaction.valid_until_block
|
25
|
+
|
26
|
+
encoded_tx = Protos::Transaction.encode(tx)
|
27
|
+
|
28
|
+
private_key_bytes = AppChain::Utils.to_bytes(private_key)
|
29
|
+
|
30
|
+
protobuf_hash = Utils.keccak256(encoded_tx)
|
31
|
+
|
32
|
+
signature = Ciri::Crypto.ecdsa_signature(private_key_bytes, protobuf_hash).signature
|
33
|
+
|
34
|
+
unverified_tx = Protos::UnverifiedTransaction.new(transaction: tx, signature: signature)
|
35
|
+
|
36
|
+
encoded_unverified_tx = Protos::UnverifiedTransaction.encode(unverified_tx)
|
37
|
+
|
38
|
+
AppChain::Utils.from_bytes(encoded_unverified_tx)
|
39
|
+
end
|
40
|
+
|
41
|
+
# unsign transaction
|
42
|
+
#
|
43
|
+
# @param tx_content [String] hex string
|
44
|
+
def decode(tx_content)
|
45
|
+
content_bytes = AppChain::Utils.to_bytes(tx_content)
|
46
|
+
unverified_transaction = Protos::UnverifiedTransaction.decode(content_bytes)
|
47
|
+
|
48
|
+
signature = unverified_transaction["signature"]
|
49
|
+
|
50
|
+
transaction = unverified_transaction["transaction"]
|
51
|
+
msg = Protos::Transaction.encode(transaction)
|
52
|
+
msg_hash = AppChain::Utils.keccak256(msg)
|
53
|
+
pubkey = Ciri::Crypto.ecdsa_recover(msg_hash, signature)
|
54
|
+
pubkey_hex = Utils.from_bytes(pubkey[1..-1])
|
55
|
+
|
56
|
+
from_address = Utils.keccak256(pubkey[1..-1])[-20..-1]
|
57
|
+
from_address_hex = Utils.from_bytes(from_address)
|
58
|
+
|
59
|
+
sender = {
|
60
|
+
"address" => from_address_hex,
|
61
|
+
"public_key" => pubkey_hex
|
62
|
+
}
|
63
|
+
|
64
|
+
{
|
65
|
+
"unverified_transaction" => unverified_transaction,
|
66
|
+
"sender" => sender
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# @param value [String] hex string with or without `0x` prefix
|
73
|
+
# @return [String] byte code string
|
74
|
+
def process_value(value)
|
75
|
+
AppChain::Utils.to_bytes(AppChain::Utils.remove_hex_prefix(value).rjust(64, "0"))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AppChain
|
4
|
+
class Utils
|
5
|
+
HEX_PREFIX = "0x"
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# add `0x` prefix to hex string
|
9
|
+
#
|
10
|
+
# @param hex [String]
|
11
|
+
def add_hex_prefix(hex)
|
12
|
+
return if hex.nil?
|
13
|
+
return hex if hex.start_with?(HEX_PREFIX)
|
14
|
+
|
15
|
+
HEX_PREFIX + hex
|
16
|
+
end
|
17
|
+
|
18
|
+
# remove `0x` prefix from hex string
|
19
|
+
#
|
20
|
+
# @param hex [String]
|
21
|
+
def remove_hex_prefix(hex)
|
22
|
+
return if hex.nil?
|
23
|
+
return hex.gsub(HEX_PREFIX, "") if hex.start_with?(HEX_PREFIX)
|
24
|
+
|
25
|
+
hex
|
26
|
+
end
|
27
|
+
|
28
|
+
# convert decimal value to hex string without `0x` prefix
|
29
|
+
#
|
30
|
+
# @param decimal [Integer]
|
31
|
+
# @return [String]
|
32
|
+
def to_hex(decimal)
|
33
|
+
add_hex_prefix decimal.to_s(16)
|
34
|
+
end
|
35
|
+
|
36
|
+
# convert hex string to decimal value
|
37
|
+
#
|
38
|
+
# @param hex [String]
|
39
|
+
# @return [Integer]
|
40
|
+
def to_decimal(hex)
|
41
|
+
hex.hex
|
42
|
+
end
|
43
|
+
|
44
|
+
# to byte code value
|
45
|
+
# remove `0x` prefix first
|
46
|
+
#
|
47
|
+
# @param str [String] normal string
|
48
|
+
# @return [String] byte code string
|
49
|
+
def to_bytes(str)
|
50
|
+
[AppChain::Utils.remove_hex_prefix(str)].pack("H*")
|
51
|
+
end
|
52
|
+
|
53
|
+
# byte code to string value, with `0x` prefix
|
54
|
+
#
|
55
|
+
# @param bytes_str [String] byte code string
|
56
|
+
# @return [String] normal string
|
57
|
+
def from_bytes(bytes_str)
|
58
|
+
AppChain::Utils.add_hex_prefix(bytes_str.unpack1("H*"))
|
59
|
+
end
|
60
|
+
|
61
|
+
# keccak 256 hash
|
62
|
+
#
|
63
|
+
def keccak256(*data)
|
64
|
+
Ciri::Utils.keccak(*data)
|
65
|
+
end
|
66
|
+
|
67
|
+
# get nonce
|
68
|
+
#
|
69
|
+
# @return [String]
|
70
|
+
def nonce
|
71
|
+
SecureRandom.hex
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "web3/eth"
|
4
|
+
|
5
|
+
module Web3
|
6
|
+
module Eth
|
7
|
+
class Contract
|
8
|
+
class ContractInstance
|
9
|
+
def function_data(method_name, *args)
|
10
|
+
@contract.function_data(method_name.to_s, args)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ContractMethod
|
15
|
+
def function_data(args)
|
16
|
+
["0x" + signature_hash + encode_hex(encode_abi(input_types, args)), output_types]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def function_data(method_name, args)
|
21
|
+
function = functions[method_name]
|
22
|
+
raise "No method found in ABI: #{method_name}" unless function
|
23
|
+
|
24
|
+
function.function_data args
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: appchain.rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- classicalliu
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-10-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.11'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.11'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: awesome_print
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.8'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.8'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.59'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.59'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: google-protobuf
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.6'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.6'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: ciri-crypto
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.1.1
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.1.1
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: faraday
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 0.15.3
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 0.15.3
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: activesupport
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 5.2.1
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 5.2.1
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: web3-eth
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: 0.2.16
|
160
|
+
type: :runtime
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 0.2.16
|
167
|
+
description: Ruby Nervos AppChain SDK for signature and rpc call
|
168
|
+
email:
|
169
|
+
- classicalliu@gmail.com
|
170
|
+
executables: []
|
171
|
+
extensions: []
|
172
|
+
extra_rdoc_files: []
|
173
|
+
files:
|
174
|
+
- ".gitignore"
|
175
|
+
- ".gitmodules"
|
176
|
+
- ".pryrc"
|
177
|
+
- ".rspec"
|
178
|
+
- ".rubocop.yml"
|
179
|
+
- ".travis.yml"
|
180
|
+
- CODE_OF_CONDUCT.md
|
181
|
+
- Gemfile
|
182
|
+
- Gemfile.lock
|
183
|
+
- LICENSE.txt
|
184
|
+
- README.md
|
185
|
+
- Rakefile
|
186
|
+
- appchain.gemspec
|
187
|
+
- bin/console
|
188
|
+
- bin/setup
|
189
|
+
- lib/appchain.rb
|
190
|
+
- lib/appchain/address.rb
|
191
|
+
- lib/appchain/client.rb
|
192
|
+
- lib/appchain/contract.rb
|
193
|
+
- lib/appchain/http.rb
|
194
|
+
- lib/appchain/protos/blockchain_pb.rb
|
195
|
+
- lib/appchain/rpc.rb
|
196
|
+
- lib/appchain/transaction.rb
|
197
|
+
- lib/appchain/transaction_signer.rb
|
198
|
+
- lib/appchain/utils.rb
|
199
|
+
- lib/appchain/version.rb
|
200
|
+
- lib/web3_eth/contract.rb
|
201
|
+
homepage: https://github.com/cryptape/appchain.rb
|
202
|
+
licenses:
|
203
|
+
- MIT
|
204
|
+
metadata:
|
205
|
+
allowed_push_host: https://rubygems.org
|
206
|
+
post_install_message:
|
207
|
+
rdoc_options: []
|
208
|
+
require_paths:
|
209
|
+
- lib
|
210
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
211
|
+
requirements:
|
212
|
+
- - ">="
|
213
|
+
- !ruby/object:Gem::Version
|
214
|
+
version: '0'
|
215
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
216
|
+
requirements:
|
217
|
+
- - ">="
|
218
|
+
- !ruby/object:Gem::Version
|
219
|
+
version: '0'
|
220
|
+
requirements: []
|
221
|
+
rubyforge_project:
|
222
|
+
rubygems_version: 2.7.6
|
223
|
+
signing_key:
|
224
|
+
specification_version: 4
|
225
|
+
summary: Ruby Nervos AppChain SDK
|
226
|
+
test_files: []
|