facetq 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 62514c7ce665930ee9a2bfed08a4b4cd6b03a40ad5435bb27f36a28855a68e49
4
- data.tar.gz: 48c9bd928542012c9da8369b5ed3542092fb905ce2069d4e4dab49e4ccd09af2
3
+ metadata.gz: 6b77cfad6fa050f005e3f8b15524d6b8cfc17ed626d3cd246e76dc8d5d4fed28
4
+ data.tar.gz: 66c7cd8926bb21f8fc6c3f14396a66247215063c1d9a0792b5f3e900e076e698
5
5
  SHA512:
6
- metadata.gz: aace02cbb67889f09178f259e86f1d0610941ba033d64df377cfae01f176dbf5117b002799448cfd7d34945ce9ed3d0a5e38acb61383ce9a86bb9f252aaf5beb
7
- data.tar.gz: 1a342b27a236f3f1adddf1c4710622c212086ae1002333efbf38e4d5d985e9201fbd1873f01ae3096f8aca8ec05c9d889f5007cef14c005e8dc26ff8e660a7ed
6
+ metadata.gz: 7b2ea766d1877ce7de26e09f04f9e11d0fde022b68f79ece6bb41be87e29aa007154e36bd3ffa9df22b19f3757240b54e492791d5fbe3d954e3731679f3677c4
7
+ data.tar.gz: 2d19007f0c709e9368a5cd78dce21e5a5f43af3c1bd599ae095e8a961bcfbab3c8b7636b152624b441457ce77519c182fc8b813a05bad5a4e0ef660723102f07
data/CHANGELOG.md CHANGED
@@ -1,3 +1,4 @@
1
+ ### 0.1.0
1
2
  ### 0.0.1 / 2023-12-07
2
3
 
3
4
  * Everything is new. First release
data/Manifest.txt CHANGED
@@ -3,6 +3,13 @@ Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
5
  lib/facetq.rb
6
- lib/facetq/eth_block.rb
7
- lib/facetq/ethscription.rb
8
- lib/facetq/transaction_receipt.rb
6
+ lib/facetq/json_sorter.rb
7
+ lib/facetq/models/contract.rb
8
+ lib/facetq/models/contract_artifact.rb
9
+ lib/facetq/models/contract_call.rb
10
+ lib/facetq/models/contract_state.rb
11
+ lib/facetq/models/contract_transaction.rb
12
+ lib/facetq/models/eth_block.rb
13
+ lib/facetq/models/ethscription.rb
14
+ lib/facetq/models/system_config_version.rb
15
+ lib/facetq/models/transaction_receipt.rb
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Facet Q - Facet Models For Easy SQL Database Queries
1
+ # Facet Q - Facet Models For SQL Database Queries
2
2
 
3
- facetq - "stand-alone" facet (activerecord) models for easy sql database queries and more
3
+ facetq - "stand-alone" facet (activerecord) models for easy (re)use for sql database queries and more
4
4
 
5
5
  * home :: [github.com/0xCompute/rubidity](https://github.com/0xCompute/rubidity)
6
6
  * bugs :: [github.com/0xCompute/rubidity/issues](https://github.com/0xCompute/rubidity/issues)
@@ -16,10 +16,10 @@ require 'facetq'
16
16
 
17
17
  ## step 1: connect to database
18
18
  config = {
19
- adapter: 'postgresql'
20
- encoding: 'unicode'
21
- database: 'ethscriptions_vm_development'
22
- username: '<your username here>'
19
+ adapter: 'postgresql',
20
+ encoding: 'unicode',
21
+ database: 'ethscriptions_vm_development',
22
+ username: '<your username here>',
23
23
  password: '<your password here>'
24
24
  }
25
25
  ActiveRecord::Base.establish_connection( config )
@@ -28,9 +28,22 @@ ActiveRecord::Base.establish_connection( config )
28
28
  puts " #{EthBlock.count} block(s)"
29
29
  puts " #{Ethscription.count} ethscription(s)"
30
30
  puts " #{TransactionReceipt.count} receipt(s)"
31
- #=> 19998 block(s)
32
- # 1 ethscription(s)
33
- # 0 receipt(s)
31
+ puts " #{ContractArtifact.count} contract artifact(s)"
32
+ puts " #{Contract.count} contract(s)"
33
+ puts " #{ContractTransaction.count} contract transaction(s)"
34
+ puts " #{ContractCall.count} contract call(s)"
35
+ puts " #{ContractState.count} countract state(s)"
36
+ puts " #{SystemConfigVersion.count} system config version(s)"
37
+ #=> 107353 block(s)
38
+ # 294056 ethscription(s)
39
+ # 33798 receipt(s)
40
+ # 8 contract artifact(s)
41
+ # 38 contract(s)
42
+ # 33798 contract transaction(s)
43
+ # 34295 contract call(s)
44
+ # 29541 countract state(s)
45
+ # 5 system config version(s)
46
+
34
47
 
35
48
  ## lets try some more queries
36
49
  data = EthBlock.order(:block_number).limit(1)
@@ -58,6 +71,8 @@ pp data.as_json
58
71
  # "processing_state"=>"complete",
59
72
  # "transaction_count"=>0}]
60
73
 
74
+
75
+ # and so forth
61
76
  ```
62
77
 
63
78
  That's it for now.
data/Rakefile CHANGED
@@ -3,9 +3,9 @@ require 'hoe'
3
3
 
4
4
 
5
5
  Hoe.spec 'facetq' do
6
- self.version = '0.0.1'
6
+ self.version = '0.1.0'
7
7
 
8
- self.summary = 'facetq - "stand-alone" facet (activerecord) models for easy sql database queries and more'
8
+ self.summary = 'facetq - "stand-alone" facet (activerecord) models for easy (re)use for sql database queries and more'
9
9
  self.description = summary
10
10
 
11
11
  self.urls = { home: 'https://github.com/0xCompute/rubidity' }
@@ -0,0 +1,10 @@
1
+
2
+ module JsonSorter
3
+ def self.sort_hash(hash)
4
+ sorted = hash.sort_by { |k, _| [k.length, k] }
5
+
6
+ sorted.each_with_object({}) do |(key, value), result|
7
+ result[key] = value.is_a?(Hash) ? sort_hash(value) : value
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,81 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: contracts
4
+ #
5
+ # id :bigint not null, primary key
6
+ # transaction_hash :string not null
7
+ # block_number :bigint not null
8
+ # transaction_index :bigint not null
9
+ # current_type :string
10
+ # current_init_code_hash :string
11
+ # current_state :jsonb not null
12
+ # address :string not null
13
+ # deployed_successfully :boolean not null
14
+ # created_at :datetime not null
15
+ # updated_at :datetime not null
16
+ #
17
+ # Indexes
18
+ #
19
+ # idx_on_address_deployed_successfully (address) UNIQUE WHERE (deployed_successfully = true)
20
+ # index_contracts_on_address (address) UNIQUE
21
+ # index_contracts_on_current_init_code_hash (current_init_code_hash)
22
+ # index_contracts_on_current_state (current_state) USING gin
23
+ # index_contracts_on_current_type (current_type)
24
+ # index_contracts_on_deployed_successfully (deployed_successfully)
25
+ # index_contracts_on_deployed_successfully_and_address (deployed_successfully,address) UNIQUE
26
+ # index_contracts_on_transaction_hash (transaction_hash)
27
+ #
28
+ # Foreign Keys
29
+ #
30
+ # fk_rails_... (block_number => eth_blocks.block_number) ON DELETE => cascade
31
+ # fk_rails_... (transaction_hash => ethscriptions.transaction_hash) ON DELETE => cascade
32
+ #
33
+ class Contract < ActiveRecord::Base
34
+
35
+ has_many :states, primary_key: 'address', foreign_key: 'contract_address', class_name: "ContractState"
36
+ belongs_to :contract_transaction, foreign_key: :transaction_hash, primary_key: :transaction_hash, optional: true
37
+
38
+ belongs_to :ethscription, primary_key: 'transaction_hash', foreign_key: 'transaction_hash', optional: true
39
+
40
+ has_many :contract_calls, foreign_key: :effective_contract_address, primary_key: :address
41
+ has_one :transaction_receipt, through: :contract_transaction
42
+
43
+
44
+
45
+ after_initialize :set_normalized_initial_state
46
+
47
+ def set_normalized_initial_state
48
+ @normalized_initial_state = JsonSorter.sort_hash(current_state)
49
+ end
50
+
51
+ def normalized_state_changed?
52
+ @normalized_initial_state != JsonSorter.sort_hash(current_state)
53
+ end
54
+
55
+
56
+ def as_json(options = {})
57
+ super(
58
+ options.merge(
59
+ only: [
60
+ :address,
61
+ :transaction_hash,
62
+ :current_init_code_hash,
63
+ :current_type
64
+ ]
65
+ )
66
+ ).tap do |json|
67
+
68
+ if association(:transaction_receipt).loaded?
69
+ json['deployment_transaction'] = transaction_receipt
70
+ end
71
+
72
+ json['current_state'] = if options[:include_current_state]
73
+ current_state
74
+ else
75
+ {}
76
+ end
77
+
78
+ json['current_state']['contract_type'] = current_type
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,54 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: contract_artifacts
4
+ #
5
+ # id :bigint not null, primary key
6
+ # transaction_hash :string not null
7
+ # internal_transaction_index :bigint not null
8
+ # block_number :bigint not null
9
+ # transaction_index :bigint not null
10
+ # name :string not null
11
+ # source_code :text not null
12
+ # init_code_hash :string not null
13
+ # references :jsonb not null
14
+ # pragma_language :string not null
15
+ # pragma_version :string not null
16
+ # created_at :datetime not null
17
+ # updated_at :datetime not null
18
+ #
19
+ # Indexes
20
+ #
21
+ # idx_on_block_number_transaction_index_internal_tran_570359f80e (block_number,transaction_index,internal_transaction_index) UNIQUE
22
+ # idx_on_transaction_hash_internal_transaction_index_c95378cab3 (transaction_hash,internal_transaction_index) UNIQUE
23
+ # index_contract_artifacts_on_init_code_hash (init_code_hash) UNIQUE
24
+ # index_contract_artifacts_on_name (name)
25
+ #
26
+ # Foreign Keys
27
+ #
28
+ # fk_rails_... (block_number => eth_blocks.block_number) ON DELETE => cascade
29
+ # fk_rails_... (transaction_hash => ethscriptions.transaction_hash) ON DELETE => cascade
30
+ #
31
+ class ContractArtifact < ActiveRecord::Base # ApplicationRecord
32
+
33
+ belongs_to :contract_transaction, foreign_key: :transaction_hash, primary_key: :transaction_hash, optional: true
34
+
35
+ scope :newest_first, -> {
36
+ order(
37
+ block_number: :desc,
38
+ transaction_index: :desc,
39
+ internal_transaction_index: :desc
40
+ )
41
+ }
42
+
43
+ def as_json(options = {})
44
+ super(
45
+ options.merge(
46
+ only: [
47
+ :name,
48
+ :source_code,
49
+ :init_code_hash
50
+ ]
51
+ )
52
+ )
53
+ end
54
+ end
@@ -0,0 +1,170 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: contract_calls
4
+ #
5
+ # id :bigint not null, primary key
6
+ # transaction_hash :string not null
7
+ # internal_transaction_index :bigint not null
8
+ # from_address :string not null
9
+ # to_contract_address :string
10
+ # created_contract_address :string
11
+ # effective_contract_address :string
12
+ # function :string
13
+ # args :jsonb not null
14
+ # call_type :string not null
15
+ # return_value :jsonb
16
+ # logs :jsonb not null
17
+ # error :jsonb
18
+ # status :string not null
19
+ # block_number :bigint not null
20
+ # block_timestamp :bigint not null
21
+ # block_blockhash :string not null
22
+ # transaction_index :bigint not null
23
+ # start_time :datetime not null
24
+ # end_time :datetime not null
25
+ # runtime_ms :integer not null
26
+ # created_at :datetime not null
27
+ # updated_at :datetime not null
28
+ #
29
+ # Indexes
30
+ #
31
+ # idx_on_block_number_txi_internal_txi (block_number,transaction_index,internal_transaction_index) UNIQUE
32
+ # idx_on_tx_hash_internal_txi (transaction_hash,internal_transaction_index) UNIQUE
33
+ # index_contract_calls_on_call_type (call_type)
34
+ # index_contract_calls_on_created_contract_address (created_contract_address) UNIQUE
35
+ # index_contract_calls_on_effective_contract_address (effective_contract_address)
36
+ # index_contract_calls_on_from_address (from_address)
37
+ # index_contract_calls_on_internal_transaction_index (internal_transaction_index)
38
+ # index_contract_calls_on_status (status)
39
+ # index_contract_calls_on_to_contract_address (to_contract_address)
40
+ #
41
+ # Foreign Keys
42
+ #
43
+ # fk_rails_... (block_number => eth_blocks.block_number) ON DELETE => cascade
44
+ # fk_rails_... (transaction_hash => ethscriptions.transaction_hash) ON DELETE => cascade
45
+ #
46
+ class ContractCall < ActiveRecord::Base # ApplicationRecord
47
+
48
+
49
+ attr_accessor :to_contract, :salt, :pending_logs, :to_contract_init_code_hash, :to_contract_source_code
50
+
51
+ belongs_to :created_contract, class_name: 'Contract', primary_key: 'address', foreign_key: 'created_contract_address', optional: true
52
+ belongs_to :called_contract, class_name: 'Contract', primary_key: 'address', foreign_key: 'to_contract_address', optional: true
53
+ belongs_to :effective_contract, class_name: 'Contract', primary_key: 'address', foreign_key: 'effective_contract_address', optional: true
54
+
55
+ belongs_to :contract_transaction, foreign_key: :transaction_hash, primary_key: :transaction_hash, optional: true, inverse_of: :contract_calls
56
+
57
+ belongs_to :ethscription, primary_key: 'transaction_hash', foreign_key: 'transaction_hash', optional: true
58
+
59
+ scope :newest_first, -> { order(
60
+ block_number: :desc,
61
+ transaction_index: :desc,
62
+ internal_transaction_index: :desc
63
+ ) }
64
+
65
+
66
+
67
+
68
+ def contract_nonce
69
+ in_memory = contract_transaction.contract_calls.count do |call|
70
+ call.from_address == from_address &&
71
+ call.is_create? &&
72
+ call.success?
73
+ end
74
+
75
+ scope = ContractCall.where(
76
+ from_address: from_address,
77
+ call_type: :create,
78
+ status: :success
79
+ )
80
+
81
+ in_memory + scope.count
82
+ end
83
+
84
+ def eoa_nonce
85
+ scope = ContractCall.where(
86
+ from_address: from_address,
87
+ call_type: [:create, :call]
88
+ )
89
+
90
+ scope.count
91
+ end
92
+
93
+ def current_nonce
94
+ raise "Not possible" unless is_create?
95
+
96
+ contract_initiated? ? contract_nonce : eoa_nonce
97
+ end
98
+
99
+ def contract_initiated?
100
+ internal_transaction_index > 0
101
+ end
102
+
103
+
104
+ def to
105
+ to_contract_address
106
+ end
107
+
108
+ def from
109
+ from_address
110
+ end
111
+
112
+ def contract_address
113
+ created_contract_address
114
+ end
115
+
116
+ def to_or_contract_address
117
+ to || contract_address
118
+ end
119
+
120
+ def as_json(options = {})
121
+ super(
122
+ options.merge(
123
+ only: [
124
+ :transaction_hash,
125
+ :block_blockhash,
126
+ :block_timestamp,
127
+ :block_number,
128
+ :transaction_index,
129
+ :internal_transaction_index,
130
+ :function,
131
+ :args,
132
+ :call_type,
133
+ :return_value,
134
+ :logs,
135
+ :error,
136
+ :status,
137
+ :runtime_ms,
138
+ :effective_contract_address
139
+ ],
140
+ methods: [:to, :from, :contract_address, :to_or_contract_address]
141
+ )
142
+ )
143
+ end
144
+
145
+ def calculated_runtime_ms
146
+ (end_time - start_time) * 1000
147
+ end
148
+
149
+ def is_static_call?
150
+ call_type.to_s == "static_call"
151
+ end
152
+
153
+ def is_create?
154
+ call_type.to_s == "create"
155
+ end
156
+
157
+ def is_call?
158
+ call_type.to_s == "call"
159
+ end
160
+
161
+ def failure?
162
+ status.to_s == 'failure'
163
+ end
164
+
165
+ def success?
166
+ status.to_s == 'success'
167
+ end
168
+
169
+
170
+ end
@@ -0,0 +1,54 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: contract_states
4
+ #
5
+ # id :bigint not null, primary key
6
+ # transaction_hash :string not null
7
+ # type :string not null
8
+ # init_code_hash :string not null
9
+ # state :jsonb not null
10
+ # block_number :bigint not null
11
+ # transaction_index :bigint not null
12
+ # contract_address :string not null
13
+ # created_at :datetime not null
14
+ # updated_at :datetime not null
15
+ #
16
+ # Indexes
17
+ #
18
+ # index_contract_states_on_addr_block_number_tx_index (contract_address,block_number,transaction_index) UNIQUE
19
+ # index_contract_states_on_contract_address (contract_address)
20
+ # index_contract_states_on_contract_address_and_transaction_hash (contract_address,transaction_hash) UNIQUE
21
+ # index_contract_states_on_state (state) USING gin
22
+ # index_contract_states_on_transaction_hash (transaction_hash)
23
+ #
24
+ # Foreign Keys
25
+ #
26
+ # fk_rails_... (block_number => eth_blocks.block_number) ON DELETE => cascade
27
+ # fk_rails_... (contract_address => contracts.address) ON DELETE => cascade
28
+ # fk_rails_... (transaction_hash => ethscriptions.transaction_hash) ON DELETE => cascade
29
+ #
30
+ class ContractState < ActiveRecord::Base
31
+ self.inheritance_column = :_type_disabled
32
+
33
+ belongs_to :contract, foreign_key: :contract_address, primary_key: :address, optional: true
34
+ belongs_to :contract_transaction, foreign_key: :transaction_hash, primary_key: :transaction_hash, optional: true
35
+ belongs_to :ethscription,
36
+ primary_key: 'transaction_hash', foreign_key: 'transaction_hash',
37
+ optional: true
38
+
39
+ scope :newest_first, -> {
40
+ order(block_number: :desc, transaction_index: :desc)
41
+ }
42
+
43
+ def as_json(options = {})
44
+ super(
45
+ options.merge(
46
+ only: [
47
+ :transaction_hash,
48
+ :contract_address,
49
+ :state,
50
+ ]
51
+ )
52
+ )
53
+ end
54
+ end
@@ -0,0 +1,45 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: contract_transactions
4
+ #
5
+ # id :bigint not null, primary key
6
+ # transaction_hash :string not null
7
+ # block_blockhash :string not null
8
+ # block_timestamp :bigint not null
9
+ # block_number :bigint not null
10
+ # transaction_index :bigint not null
11
+ # created_at :datetime not null
12
+ # updated_at :datetime not null
13
+ #
14
+ # Indexes
15
+ #
16
+ # index_contract_transactions_on_transaction_hash (transaction_hash) UNIQUE
17
+ # index_contract_txs_on_block_number_and_tx_index (block_number,transaction_index) UNIQUE
18
+ #
19
+ # Foreign Keys
20
+ #
21
+ # fk_rails_... (block_number => eth_blocks.block_number) ON DELETE => cascade
22
+ # fk_rails_... (transaction_hash => ethscriptions.transaction_hash) ON DELETE => cascade
23
+ #
24
+ class ContractTransaction < ActiveRecord::Base
25
+
26
+ belongs_to :ethscription, primary_key: :transaction_hash, foreign_key: :transaction_hash, optional: true
27
+ has_one :transaction_receipt, foreign_key: :transaction_hash, primary_key: :transaction_hash
28
+ has_many :contract_states, foreign_key: :transaction_hash, primary_key: :transaction_hash
29
+ has_many :contract_calls, foreign_key: :transaction_hash, primary_key: :transaction_hash, inverse_of: :contract_transaction
30
+ has_many :contracts, foreign_key: :transaction_hash, primary_key: :transaction_hash
31
+ has_many :contract_artifacts, foreign_key: :transaction_hash, primary_key: :transaction_hash
32
+
33
+ attr_accessor :tx_origin, :payload
34
+
35
+ def self.transaction_mimetype
36
+ "application/vnd.facet.tx+json"
37
+ end
38
+
39
+
40
+
41
+
42
+ def status
43
+ contract_calls.any?(&:failure?) ? :failure : :success
44
+ end
45
+ end
@@ -0,0 +1,64 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: eth_blocks
4
+ #
5
+ # id :bigint not null, primary key
6
+ # block_number :bigint not null
7
+ # timestamp :bigint not null
8
+ # blockhash :string not null
9
+ # parent_blockhash :string not null
10
+ # imported_at :datetime not null
11
+ # processing_state :string not null
12
+ # transaction_count :bigint
13
+ # runtime_ms :integer
14
+ # created_at :datetime not null
15
+ # updated_at :datetime not null
16
+ #
17
+ # Indexes
18
+ #
19
+ # index_eth_blocks_on_block_number (block_number) UNIQUE
20
+ # index_eth_blocks_on_block_number_completed (block_number) WHERE ((processing_state)::text = 'complete'::text)
21
+ # index_eth_blocks_on_block_number_pending (block_number) WHERE ((processing_state)::text = 'pending'::text)
22
+ # index_eth_blocks_on_blockhash (blockhash) UNIQUE
23
+ # index_eth_blocks_on_imported_at (imported_at)
24
+ # index_eth_blocks_on_imported_at_and_processing_state (imported_at,processing_state)
25
+ # index_eth_blocks_on_parent_blockhash (parent_blockhash) UNIQUE
26
+ # index_eth_blocks_on_processing_state (processing_state)
27
+ # index_eth_blocks_on_timestamp (timestamp)
28
+ #
29
+
30
+
31
+ class EthBlock < ActiveRecord::Base # ApplicationRecord
32
+
33
+ has_many :ethscriptions, foreign_key: :block_number, primary_key: :block_number
34
+ has_many :transaction_receipts, foreign_key: :block_number, primary_key: :block_number
35
+
36
+ scope :newest_first, -> { order(block_number: :desc) }
37
+ scope :oldest_first, -> { order(block_number: :asc) }
38
+
39
+ scope :processed, -> { where.not(processing_state: "pending") }
40
+
41
+ def self.max_processed_block_number
42
+ EthBlock.processed.maximum(:block_number).to_i
43
+ end
44
+
45
+
46
+
47
+ def as_json(options = {})
48
+ super(options.merge(
49
+ only: [
50
+ :block_number,
51
+ :timestamp,
52
+ :blockhash,
53
+ :parent_blockhash,
54
+ :imported_at,
55
+ :processing_state,
56
+ :transaction_count,
57
+ ]
58
+ )).tap do |json|
59
+ if association(:transaction_receipts).loaded?
60
+ json[:transaction_receipts] = transaction_receipts.map(&:as_json)
61
+ end
62
+ end.with_indifferent_access
63
+ end
64
+ end
@@ -0,0 +1,79 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: ethscriptions
4
+ #
5
+ # id :bigint not null, primary key
6
+ # transaction_hash :string not null
7
+ # block_number :bigint not null
8
+ # block_blockhash :string not null
9
+ # transaction_index :bigint not null
10
+ # creator :string not null
11
+ # initial_owner :string not null
12
+ # block_timestamp :bigint not null
13
+ # content_uri :text not null
14
+ # mimetype :string not null
15
+ # processed_at :datetime
16
+ # processing_state :string not null
17
+ # processing_error :string
18
+ # gas_price :bigint
19
+ # gas_used :bigint
20
+ # transaction_fee :bigint
21
+ # created_at :datetime not null
22
+ # updated_at :datetime not null
23
+ #
24
+ # Indexes
25
+ #
26
+ # index_ethscriptions_on_block_number_and_transaction_index (block_number,transaction_index) UNIQUE
27
+ # index_ethscriptions_on_processing_state (processing_state)
28
+ # index_ethscriptions_on_transaction_hash (transaction_hash) UNIQUE
29
+ #
30
+ # Foreign Keys
31
+ #
32
+ # fk_rails_... (block_number => eth_blocks.block_number) ON DELETE => cascade
33
+ #
34
+
35
+
36
+ class Ethscription < ActiveRecord::Base # ApplicationRecord
37
+
38
+ belongs_to :eth_block, foreign_key: :block_number, primary_key: :block_number, optional: true
39
+
40
+ has_many :contracts, primary_key: 'transaction_hash', foreign_key: 'transaction_hash'
41
+
42
+ has_one :transaction_receipt, primary_key: 'transaction_hash', foreign_key: 'transaction_hash'
43
+
44
+ has_one :contract_transaction, primary_key: 'transaction_hash', foreign_key: 'transaction_hash'
45
+ has_one :system_config_version, primary_key: 'transaction_hash', foreign_key: 'transaction_hash'
46
+ has_many :contract_states, primary_key: 'transaction_hash', foreign_key: 'transaction_hash'
47
+
48
+ before_validation :downcase_hex_fields
49
+
50
+ scope :newest_first, -> { order(block_number: :desc, transaction_index: :desc) }
51
+ scope :oldest_first, -> { order(block_number: :asc, transaction_index: :asc) }
52
+
53
+ scope :unprocessed, -> { where(processing_state: "pending") }
54
+
55
+ def content
56
+ content_uri[/.*?,(.*)/, 1]
57
+ end
58
+
59
+ def parsed_content
60
+ JSON.parse(content)
61
+ end
62
+
63
+ def processed?
64
+ processing_state != "pending"
65
+ end
66
+
67
+ def self.required_initial_owner
68
+ "0x00000000000000000000000000000000000face7"
69
+ end
70
+
71
+
72
+ private
73
+
74
+ def downcase_hex_fields
75
+ self.transaction_hash = transaction_hash.downcase
76
+ self.creator = creator.downcase
77
+ self.initial_owner = initial_owner.downcase
78
+ end
79
+ end
@@ -0,0 +1,71 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: system_config_versions
4
+ #
5
+ # id :bigint not null, primary key
6
+ # transaction_hash :string not null
7
+ # block_number :bigint not null
8
+ # transaction_index :bigint not null
9
+ # supported_contracts :jsonb not null
10
+ # start_block_number :bigint
11
+ # admin_address :string
12
+ # created_at :datetime not null
13
+ # updated_at :datetime not null
14
+ #
15
+ # Indexes
16
+ #
17
+ # idx_on_block_number_transaction_index_efc8dd9c1d (block_number,transaction_index) UNIQUE
18
+ # index_system_config_versions_on_transaction_hash (transaction_hash) UNIQUE
19
+ #
20
+ # Foreign Keys
21
+ #
22
+ # fk_rails_... (block_number => eth_blocks.block_number) ON DELETE => cascade
23
+ # fk_rails_... (transaction_hash => ethscriptions.transaction_hash) ON DELETE => cascade
24
+ #
25
+ class SystemConfigVersion < ActiveRecord::Base # ApplicationRecord
26
+
27
+ belongs_to :ethscription,
28
+ primary_key: 'transaction_hash', foreign_key: 'transaction_hash', optional: true
29
+
30
+ scope :newest_first, -> {
31
+ order(block_number: :desc, transaction_index: :desc)
32
+ }
33
+
34
+ def self.latest_tx_hash
35
+ newest_first.limit(1).pluck(:transaction_hash).first
36
+ end
37
+
38
+ def self.system_mimetype
39
+ "application/vnd.facet.system+json"
40
+ end
41
+
42
+
43
+ def operation_data
44
+ JSON.parse(ethscription.content).fetch('data')
45
+ rescue JSON::ParserError => e
46
+ raise "JSON parse error: #{e.message}"
47
+ end
48
+
49
+
50
+ def self.current
51
+ (newest_first.first || new).freeze
52
+ end
53
+
54
+ =begin
55
+ def as_json(options = {})
56
+ super(
57
+ options.merge(
58
+ only: [
59
+ :supported_contracts,
60
+ :block_number,
61
+ :transaction_index,
62
+ ]
63
+ )
64
+ )
65
+ end
66
+ =end
67
+
68
+ def self.current_admin_address
69
+ current.admin_address || ENV.fetch("INITIAL_SYSTEM_CONFIG_ADMIN_ADDRESS").downcase
70
+ end
71
+ end
@@ -0,0 +1,119 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: transaction_receipts
4
+ #
5
+ # id :bigint not null, primary key
6
+ # transaction_hash :string not null
7
+ # from_address :string not null
8
+ # status :string not null
9
+ # function :string
10
+ # args :jsonb not null
11
+ # logs :jsonb not null
12
+ # block_timestamp :bigint not null
13
+ # error :jsonb
14
+ # to_contract_address :string
15
+ # effective_contract_address :string
16
+ # created_contract_address :string
17
+ # block_number :bigint not null
18
+ # transaction_index :bigint not null
19
+ # block_blockhash :string not null
20
+ # return_value :jsonb
21
+ # runtime_ms :integer not null
22
+ # call_type :string not null
23
+ # gas_price :bigint
24
+ # gas_used :bigint
25
+ # transaction_fee :bigint
26
+ # created_at :datetime not null
27
+ # updated_at :datetime not null
28
+ #
29
+ # Indexes
30
+ #
31
+ # index_contract_tx_receipts_on_block_number_and_tx_index (block_number,transaction_index) UNIQUE
32
+ # index_transaction_receipts_on_block_number (block_number)
33
+ # index_transaction_receipts_on_block_number_and_runtime_ms (block_number,runtime_ms)
34
+ # index_transaction_receipts_on_created_contract_address (created_contract_address)
35
+ # index_transaction_receipts_on_effective_contract_address (effective_contract_address)
36
+ # index_transaction_receipts_on_runtime_ms (runtime_ms)
37
+ # index_transaction_receipts_on_to_contract_address (to_contract_address)
38
+ # index_transaction_receipts_on_transaction_hash (transaction_hash) UNIQUE
39
+ #
40
+ # Foreign Keys
41
+ #
42
+ # fk_rails_... (block_number => eth_blocks.block_number) ON DELETE => cascade
43
+ # fk_rails_... (transaction_hash => ethscriptions.transaction_hash) ON DELETE => cascade
44
+ #
45
+
46
+
47
+ class TransactionReceipt < ActiveRecord::Base # ApplicationRecord
48
+ belongs_to :eth_block, foreign_key: :block_number, primary_key: :block_number
49
+
50
+ belongs_to :contract, primary_key: 'address', foreign_key: 'effective_contract_address', optional: true
51
+ belongs_to :contract_transaction, foreign_key: :transaction_hash, primary_key: :transaction_hash, optional: true
52
+
53
+ belongs_to :ethscription,
54
+ primary_key: 'transaction_hash', foreign_key: 'transaction_hash',
55
+ optional: true
56
+
57
+ scope :newest_first, -> { order(block_number: :desc, transaction_index: :desc) }
58
+ scope :oldest_first, -> { order(block_number: :asc, transaction_index: :asc) }
59
+
60
+
61
+ def contract
62
+ Contract.find_by_address(address)
63
+ end
64
+
65
+ def address
66
+ effective_contract_address
67
+ end
68
+
69
+ def to
70
+ to_contract_address
71
+ end
72
+
73
+ def from
74
+ from_address
75
+ end
76
+
77
+ def contract_address
78
+ created_contract_address
79
+ end
80
+
81
+ def to_or_contract_address
82
+ to || contract_address
83
+ end
84
+
85
+ def as_json(options = {})
86
+ super(
87
+ options.merge(
88
+ only: [
89
+ :transaction_hash,
90
+ :call_type,
91
+ :runtime_ms,
92
+ :block_timestamp,
93
+ :status,
94
+ :function,
95
+ :args,
96
+ :error,
97
+ :logs,
98
+ :block_blockhash,
99
+ :block_number,
100
+ :transaction_index,
101
+ :gas_price,
102
+ :gas_used,
103
+ :transaction_fee,
104
+ :return_value,
105
+ :effective_contract_address
106
+ ],
107
+ methods: [:to, :from, :contract_address, :to_or_contract_address]
108
+ )
109
+ ).with_indifferent_access
110
+ end
111
+
112
+ def failure?
113
+ status.to_s == 'failure'
114
+ end
115
+
116
+ def success?
117
+ status.to_s == 'success'
118
+ end
119
+ end
data/lib/facetq.rb CHANGED
@@ -7,11 +7,18 @@ require 'active_record'
7
7
  ## class ApplicationRecord < ActiveRecord::Base
8
8
  ## end
9
9
 
10
-
11
-
12
- require_relative 'facetq/eth_block'
13
- require_relative 'facetq/ethscription'
14
- require_relative 'facetq/transaction_receipt'
10
+ require_relative 'facetq/json_sorter'
11
+
12
+
13
+ require_relative 'facetq/models/eth_block'
14
+ require_relative 'facetq/models/ethscription'
15
+ require_relative 'facetq/models/transaction_receipt'
16
+ require_relative 'facetq/models/contract'
17
+ require_relative 'facetq/models/contract_call'
18
+ require_relative 'facetq/models/contract_state'
19
+ require_relative 'facetq/models/contract_transaction'
20
+ require_relative 'facetq/models/contract_artifact'
21
+ require_relative 'facetq/models/system_config_version'
15
22
 
16
23
 
17
24
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: facetq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
@@ -58,8 +58,8 @@ dependencies:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: '4.0'
61
- description: facetq - "stand-alone" facet (activerecord) models for easy sql database
62
- queries and more
61
+ description: facetq - "stand-alone" facet (activerecord) models for easy (re)use for
62
+ sql database queries and more
63
63
  email: gerald.bauer@gmail.com
64
64
  executables: []
65
65
  extensions: []
@@ -73,9 +73,16 @@ files:
73
73
  - README.md
74
74
  - Rakefile
75
75
  - lib/facetq.rb
76
- - lib/facetq/eth_block.rb
77
- - lib/facetq/ethscription.rb
78
- - lib/facetq/transaction_receipt.rb
76
+ - lib/facetq/json_sorter.rb
77
+ - lib/facetq/models/contract.rb
78
+ - lib/facetq/models/contract_artifact.rb
79
+ - lib/facetq/models/contract_call.rb
80
+ - lib/facetq/models/contract_state.rb
81
+ - lib/facetq/models/contract_transaction.rb
82
+ - lib/facetq/models/eth_block.rb
83
+ - lib/facetq/models/ethscription.rb
84
+ - lib/facetq/models/system_config_version.rb
85
+ - lib/facetq/models/transaction_receipt.rb
79
86
  homepage: https://github.com/0xCompute/rubidity
80
87
  licenses:
81
88
  - Public Domain
@@ -100,6 +107,6 @@ requirements: []
100
107
  rubygems_version: 3.4.10
101
108
  signing_key:
102
109
  specification_version: 4
103
- summary: facetq - "stand-alone" facet (activerecord) models for easy sql database
104
- queries and more
110
+ summary: facetq - "stand-alone" facet (activerecord) models for easy (re)use for sql
111
+ database queries and more
105
112
  test_files: []
@@ -1,39 +0,0 @@
1
-
2
- ## check if applicationrecord works
3
- ## in actierecord "stand-alone" mode??
4
-
5
-
6
- class EthBlock < ActiveRecord::Base # ApplicationRecord
7
-
8
- has_many :ethscriptions, foreign_key: :block_number, primary_key: :block_number
9
- has_many :transaction_receipts, foreign_key: :block_number, primary_key: :block_number
10
-
11
- scope :newest_first, -> { order(block_number: :desc) }
12
- scope :oldest_first, -> { order(block_number: :asc) }
13
-
14
- scope :processed, -> { where.not(processing_state: "pending") }
15
-
16
- def self.max_processed_block_number
17
- EthBlock.processed.maximum(:block_number).to_i
18
- end
19
-
20
-
21
-
22
- def as_json(options = {})
23
- super(options.merge(
24
- only: [
25
- :block_number,
26
- :timestamp,
27
- :blockhash,
28
- :parent_blockhash,
29
- :imported_at,
30
- :processing_state,
31
- :transaction_count,
32
- ]
33
- )).tap do |json|
34
- if association(:transaction_receipts).loaded?
35
- json[:transaction_receipts] = transaction_receipts.map(&:as_json)
36
- end
37
- end.with_indifferent_access
38
- end
39
- end
@@ -1,44 +0,0 @@
1
- class Ethscription < ActiveRecord::Base # ApplicationRecord
2
-
3
- belongs_to :eth_block, foreign_key: :block_number, primary_key: :block_number, optional: true
4
-
5
- # has_many :contracts, primary_key: 'transaction_hash', foreign_key: 'transaction_hash'
6
-
7
- has_one :transaction_receipt, primary_key: 'transaction_hash', foreign_key: 'transaction_hash'
8
-
9
- # has_one :contract_transaction, primary_key: 'transaction_hash', foreign_key: 'transaction_hash'
10
- # has_one :system_config_version, primary_key: 'transaction_hash', foreign_key: 'transaction_hash'
11
- # has_many :contract_states, primary_key: 'transaction_hash', foreign_key: 'transaction_hash'
12
-
13
- before_validation :downcase_hex_fields
14
-
15
- scope :newest_first, -> { order(block_number: :desc, transaction_index: :desc) }
16
- scope :oldest_first, -> { order(block_number: :asc, transaction_index: :asc) }
17
-
18
- scope :unprocessed, -> { where(processing_state: "pending") }
19
-
20
- def content
21
- content_uri[/.*?,(.*)/, 1]
22
- end
23
-
24
- def parsed_content
25
- JSON.parse(content)
26
- end
27
-
28
- def processed?
29
- processing_state != "pending"
30
- end
31
-
32
- def self.required_initial_owner
33
- "0x00000000000000000000000000000000000face7"
34
- end
35
-
36
-
37
- private
38
-
39
- def downcase_hex_fields
40
- self.transaction_hash = transaction_hash.downcase
41
- self.creator = creator.downcase
42
- self.initial_owner = initial_owner.downcase
43
- end
44
- end
@@ -1,72 +0,0 @@
1
- class TransactionReceipt < ActiveRecord::Base # ApplicationRecord
2
- belongs_to :eth_block, foreign_key: :block_number, primary_key: :block_number
3
-
4
- # belongs_to :contract, primary_key: 'address', foreign_key: 'effective_contract_address', optional: true
5
- # belongs_to :contract_transaction, foreign_key: :transaction_hash, primary_key: :transaction_hash, optional: true
6
-
7
- belongs_to :ethscription,
8
- primary_key: 'transaction_hash', foreign_key: 'transaction_hash',
9
- optional: true
10
-
11
- scope :newest_first, -> { order(block_number: :desc, transaction_index: :desc) }
12
- scope :oldest_first, -> { order(block_number: :asc, transaction_index: :asc) }
13
-
14
- # def contract
15
- # Contract.find_by_address(address)
16
- # end
17
-
18
- def address
19
- effective_contract_address
20
- end
21
-
22
- def to
23
- to_contract_address
24
- end
25
-
26
- def from
27
- from_address
28
- end
29
-
30
- def contract_address
31
- created_contract_address
32
- end
33
-
34
- def to_or_contract_address
35
- to || contract_address
36
- end
37
-
38
- def as_json(options = {})
39
- super(
40
- options.merge(
41
- only: [
42
- :transaction_hash,
43
- :call_type,
44
- :runtime_ms,
45
- :block_timestamp,
46
- :status,
47
- :function,
48
- :args,
49
- :error,
50
- :logs,
51
- :block_blockhash,
52
- :block_number,
53
- :transaction_index,
54
- :gas_price,
55
- :gas_used,
56
- :transaction_fee,
57
- :return_value,
58
- :effective_contract_address
59
- ],
60
- methods: [:to, :from, :contract_address, :to_or_contract_address]
61
- )
62
- ).with_indifferent_access
63
- end
64
-
65
- def failure?
66
- status.to_s == 'failure'
67
- end
68
-
69
- def success?
70
- status.to_s == 'success'
71
- end
72
- end