ethscribe 0.0.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 188cf1ce52483f1154cb3ecf9bc7bbb4fcd60afa3d74543a0e1523c29e866e59
4
- data.tar.gz: c9c60dbdc3ffb69b23447a3e44e33c28788b156aed6c4f40571a9a91a3f2d1b0
3
+ metadata.gz: '09ac9a5eb1dbb35dde2105a3865bf6c67edd5469e8f9518e46949752f127991a'
4
+ data.tar.gz: 81e37a9c8a75bf4b1ec7a7ac82feccee8906a4a45636c750f7ba54e8c3797334
5
5
  SHA512:
6
- metadata.gz: d98ebfe511ec43d963697e487a3202641d16c1a1ab51b0d8239f3cd0d4a8cd2c7f939bb2b98046dcb615f475fe8f3caabbbdecfbd18b46471bb3d3b53ded6eaa
7
- data.tar.gz: 84139161c630e77dc0f20cbf0e538394179b265af5ba4b739cbc5b8efa72f857ebd36dbdd09976262d8cbfebbfb09b1f3ec55b7f859141a99df38b15777d44b1
6
+ metadata.gz: 5cc33bb70781c8490fb1f5c8c3512f22d614fa6eade666d90ec7c1e7e30a77559e42a77f0bbaa28518111b1b1b0da498c764b9627d31488e0aab3d7788919f3b
7
+ data.tar.gz: 73547597a38a756b3be3dcf8d11ee387e651dffdfea3db936f250a146288bdc74b5a7f2d575e1a9eccce9e21b1b204591e4df8436601656f35780866a29afa06
data/CHANGELOG.md CHANGED
@@ -1,3 +1,4 @@
1
+ ### 0.2.0
1
2
  ### 0.0.1 / 2023-11-20
2
3
 
3
4
  * Everything is new. First release
data/Manifest.txt CHANGED
@@ -3,3 +3,5 @@ Manifest.txt
3
3
  README.md
4
4
  Rakefile
5
5
  lib/ethscribe.rb
6
+ lib/ethscribe/api.rb
7
+ lib/ethscribe/version.rb
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Ethscribe - Inscription (Ethscription Calldata) API Wrapper & Helpers for Ethereum & Co.
1
+ # Ethscribe - Inscription / Inscribe (Ethscription Calldata) API Wrapper & Helpers for Ethereum & Co.
2
2
 
3
- ethscribe - inscription (ethscription calldata) api wrapper & helpers for Ethereum & co.
3
+ ethscribe - inscription / inscribe (ethscription calldata) api wrapper & helpers for Ethereum & co.
4
4
 
5
5
 
6
6
 
@@ -10,13 +10,95 @@ ethscribe - inscription (ethscription calldata) api wrapper & helpers for Ethe
10
10
  * rdoc :: [rubydoc.info/gems/ethscribe](http://rubydoc.info/gems/ethscribe)
11
11
 
12
12
 
13
- ## What's Ethscription Calldata / Ethereum Inscription?!
14
13
 
15
- To be done...
14
+ ## What's Ethscription Calldata - Ethereum Inscription / Inscribe?!
16
15
 
16
+ See [Introducing Ethscriptions - A new way of creating and sharing digital artifacts on the Ethereum blockchain using transaction calldata »](https://medium.com/@dumbnamenumbers/introducing-ethscriptions-698b295d6f2a)
17
17
 
18
18
 
19
19
 
20
+ ## Usage
21
+
22
+ This is a little "lite" wrapper around the ethscriptions.com api(s).
23
+
24
+
25
+ > The Ethscriptions.com API (v1)
26
+ > does not require a key, however it is rate limited.
27
+ > If you need more throughput, contact Middlemarch on Twitter.
28
+ >
29
+ > If you build something cool, also contact Middlemarch on Twitter!
30
+ >
31
+ > There is a goerli API and a mainnet API. The base URIs are:
32
+ >
33
+ > - https://goerli-api.ethscriptions.com/api
34
+ > - https://mainnet-api.ethscriptions.com/api
35
+ >
36
+ > Append the below paths, plus a query string if you want, to access the API!
37
+ >
38
+ > -- [Introducing the Ethscriptions.com API (v1)](https://medium.com/@dumbnamenumbers/introducing-the-ethscriptions-com-api-v1-6d2c507d82cd)
39
+
40
+
41
+
42
+ The (ethereum) goerli testnet api is wrapped in `Ethscribe::Api.goerli` and
43
+ the (ethereum) mainnet api is wrapped in `Ethscribe::Api.mainnet`.
44
+
45
+ Let's try the mainnet:
46
+
47
+ ```ruby
48
+ require 'ethscribe'
49
+
50
+ web = Ethscribe::Api.mainnet # or Ethscribe::Api.goerli
51
+
52
+
53
+ ## get latest 25 inscriptions (defaults: page_size=25, sort_order=desc)
54
+ pp web.ethscriptions
55
+
56
+ ## get inscriptions page 1 (same as above)
57
+ pp web.ethscriptions( page: 1 )
58
+
59
+ # get inscriptions page 2
60
+ pp web.ethscriptions( page: 2 )
61
+
62
+ # get oldest first - sort_order=asc
63
+ pp web.ethscriptions( page: 1, sort_order: 'asc' )
64
+ pp web.ethscriptions( page: 2, sort_order: 'asc' )
65
+
66
+
67
+ # get inscription by id or num
68
+ pp web.ethscription( 0 )
69
+ pp web.ethscription( 1 )
70
+ pp web.ethscription( 1000 )
71
+ pp web.ethscription( 1_000_000 )
72
+
73
+
74
+ # get inscriptions owend by <addresss>
75
+ address = '0x2a878245b52a2d46cb4327541cbc96e403a84791'
76
+ pp web.ethscriptions_owned_by( address )
77
+
78
+
79
+ # get inscription (decoded) content_data and content_type by id or num
80
+ pp web.ethscription_data( 0 )
81
+ pp web.ethscription_data( 1 )
82
+ pp web.ethscription_data( 2 )
83
+
84
+
85
+ # check if content exists (using sha256 hash)
86
+ # inscribe no. 0
87
+ sha = '2817fd9cf901e4435253881550731a5edc5e519c19de46b08e2b19a18e95143e'
88
+ pp web.ethscription_exists( sha )
89
+
90
+ # inscribe no. ??
91
+ sha = '2817fd9cf901e4435253833550731a5edc5e519c19de46b08e2b19a18e95143e'
92
+ pp web.ethscription_exists( sha )
93
+
94
+ # check the indexer (block) status
95
+ pp web.block_status
96
+ ```
97
+
98
+
99
+ That's it for now.
100
+
101
+
20
102
 
21
103
  ## Bonus - More Blockchain (Crypto) Tools, Libraries & Scripts In Ruby
22
104
 
data/Rakefile CHANGED
@@ -1,11 +1,11 @@
1
1
  require 'hoe'
2
- # require './lib/ethscribe/version.rb'
2
+ require './lib/ethscribe/version.rb'
3
3
 
4
4
 
5
5
  Hoe.spec 'ethscribe' do
6
- self.version = '0.0.1'
6
+ self.version = Ethscribe::VERSION
7
7
 
8
- self.summary = 'ethscribe - inscription (ethscription calldata) api wrapper & helpers for Ethereum & co.'
8
+ self.summary = 'ethscribe - inscription / inscribe (ethscription calldata) api wrapper & helpers for Ethereum & co.'
9
9
  self.description = summary
10
10
 
11
11
  self.urls = { home: 'https://github.com/s6ruby/rubidity' }
@@ -18,6 +18,7 @@ Hoe.spec 'ethscribe' do
18
18
  self.history_file = 'CHANGELOG.md'
19
19
 
20
20
  self.extra_deps = [
21
+ ['cocos'],
21
22
  ]
22
23
 
23
24
  self.licenses = ['Public Domain']
@@ -0,0 +1,190 @@
1
+
2
+
3
+ module Ethscribe
4
+
5
+
6
+ class Api ## change/rename Api to Client - why? why not?
7
+ def self.goerli
8
+ @goerli ||= new( 'https://goerli-api.ethscriptions.com/api' )
9
+ @goerli
10
+ end
11
+ ## todo: add test alias - why? why not?
12
+
13
+ def self.mainnet
14
+ @mainnet ||= new( 'https://api.ethscriptions.com/api' )
15
+ @mainnet
16
+ end
17
+ ## todo: add eth, main or production alias - why? why not?
18
+
19
+
20
+ def config() Ethscribe.config; end ## convenience shortcut helper
21
+
22
+
23
+ def initialize( base )
24
+ @base = base
25
+ @requests = 0 ## count requests (for delay_in_s sleeping/throttling)
26
+ end
27
+
28
+
29
+ #
30
+ # Get all ethscriptions
31
+ #
32
+ # /ethscriptions
33
+ #
34
+ # Query parameters:
35
+ # page - integer (starting at 1)
36
+ # per_page - integer (default: 25 - max: 50)
37
+ # sort_order - string "asc" or "desc" (default: desc - latest first)
38
+
39
+
40
+ def ethscriptions( page: nil, per_page: nil, sort_order: nil )
41
+ src = "#{@base}/ethscriptions"
42
+ params = []
43
+ params << ['page', page.to_s] if page
44
+ params << ['per_page', per_page.to_s] if per_page
45
+ params << ['sort_order', sort_order.to_s.downcase ] if sort_order
46
+
47
+ if params.size > 0
48
+ src += "?" + params.map { |key,value| "#{key}=#{value}" }.join('&')
49
+ end
50
+
51
+ res = get( src )
52
+ res.json ## return parsed json data - why? why not?
53
+ end
54
+
55
+ #
56
+ # Get ethscriptions owned by address
57
+ #
58
+ # /ethscriptions/owned_by/:address
59
+ #
60
+ # Query parameters: page, per_page( max 1000), sort_order (asc / desc)
61
+
62
+ def ethscriptions_owned_by( address )
63
+ src = "#{@base}/ethscriptions/owned_by/#{address}"
64
+
65
+ res = get( src )
66
+ res.json ## return parsed json data - why? why not?
67
+ end
68
+
69
+
70
+
71
+ #
72
+ # Get specific ethscription
73
+ #
74
+ # /ethscriptions/:ethscription_id
75
+ #
76
+ # Or
77
+ #
78
+ # /ethscriptions/:ethscription_number
79
+ #
80
+ # (ethscription_id is the transaction hash of the transaction that created the ethscription)
81
+
82
+ # note: use singular (overload method by args not possible in ruby)
83
+ def ethscription( id_or_num )
84
+ src = "#{@base}/ethscriptions/#{id_or_num}"
85
+ res = get( src )
86
+ res.json ## return parsed json data - why? why not?
87
+ end
88
+
89
+ #
90
+ # Get data of an ethscription
91
+ #
92
+ # /ethscriptions/:ethscription_id/data
93
+ #
94
+ # Or
95
+ #
96
+ # /ethscriptions/:ethscription_number/data
97
+ #
98
+ # This will return the ethscription's raw decoded data in the correct mimetype
99
+
100
+
101
+ ###
102
+ # use a struct-like content class - why? why not?
103
+ class Content
104
+ attr_reader :data,
105
+ :type,
106
+ :length
107
+ def initialize( data, type, length )
108
+ @data = data
109
+ @type = type
110
+ @length = length
111
+ end
112
+
113
+ alias_method :blob, :data
114
+ end ## (nested) class Content
115
+
116
+
117
+ def ethscription_data( id_or_num )
118
+ src = "#{@base}/ethscriptions/#{id_or_num}/data"
119
+ res = get( src )
120
+
121
+ content_type = res.content_type
122
+ content_length = res.content_length
123
+
124
+ ## note - content_length -- returns an integer (number)
125
+ ## puts "content_length:"
126
+ ## print content_length.inspect
127
+ ## print " - #{content_length.class.name}\n"
128
+
129
+ ## fix-fix-fix
130
+ ## if text/json/svg type etc.
131
+ ## convert to utf8 (from binary blob why? why not?) - why? why not?
132
+ ## or add text accessor to content?
133
+
134
+ content = Content.new(
135
+ res.blob,
136
+ content_type,
137
+ content_length )
138
+ content
139
+ end
140
+
141
+
142
+ ###
143
+ # Check whether content is already ethscribed
144
+ #
145
+ # /ethscriptions/exists/:sha
146
+ #
147
+ # Where sha is the sha256 of the UTF-8 data URI
148
+
149
+ # {"result":false,"ethscription":null}
150
+
151
+ def ethscription_exists( sha )
152
+ src = "#{@base}/ethscriptions/exists/#{sha}"
153
+ res = get( src )
154
+ res.json ## return parsed json data - why? why not?
155
+ end
156
+
157
+ # Determine if the indexer is behind
158
+ #
159
+ # {"current_block_number":18619883,"last_imported_block":18619883,"blocks_behind":0}
160
+
161
+ def block_status
162
+ src = "#{@base}/block_status"
163
+ res = get( src )
164
+ res.json ## return parsed json data - why? why not?
165
+ end
166
+
167
+
168
+ def get( src )
169
+ @requests += 1
170
+
171
+ if @requests > 1 && config.delay_in_s
172
+ puts "request no. #{@requests}@#{@base}; sleeping #{config.delay_in_s} sec(s)..."
173
+ sleep( config.delay_in_s )
174
+ end
175
+
176
+ res = Webclient.get( src )
177
+
178
+ if res.status.ok?
179
+ res
180
+ else
181
+ ## todo/fix: raise exception here!!!!
182
+ puts "!! ERROR - HTTP #{res.status.code} #{res.status.message} - failed web request >#{src}<; sorry"
183
+ exit 1
184
+ end
185
+ end
186
+ end # class Api
187
+
188
+
189
+ end ## module Ethscibe
190
+
@@ -0,0 +1,19 @@
1
+
2
+ module Ethscribe
3
+ MAJOR = 0 ## todo: namespace inside version or something - why? why not??
4
+ MINOR = 2
5
+ PATCH = 0
6
+ VERSION = [MAJOR,MINOR,PATCH].join('.')
7
+
8
+ def self.version
9
+ VERSION
10
+ end
11
+
12
+ def self.banner
13
+ "ethscribe/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in >#{root}<"
14
+ end
15
+
16
+ def self.root
17
+ File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
18
+ end
19
+ end
data/lib/ethscribe.rb CHANGED
@@ -1,3 +1,94 @@
1
+ require 'cocos'
1
2
 
2
- puts "Hello, Ethscribe!"
3
+
4
+
5
+ module Ethscribe
6
+ class Configuration
7
+
8
+ #######################
9
+ ## accessors
10
+ def chain=(value)
11
+ if value.is_a?( String ) || value.is_a?( Symbol )
12
+ case value.downcase.to_s
13
+ when 'mainnet' # 'main', 'eth', 'prod', 'production'
14
+ @chain = 'mainnet'
15
+ @client = Ethscribe::Api.mainnet
16
+ when 'goerli' # 'testnet', 'test'
17
+ @chain = 'goerli'
18
+ @client = Ethscribe::Api.goerli
19
+ else
20
+ raise ArgumentError, "unknown chain - expected mainnet | goerli; got #{value}"
21
+ end
22
+ else
23
+ raise ArgumentError, "only string or symbol supported for now; sorry - got: #{value.inspect} : #{value.class.name}"
24
+ end
25
+ end
26
+
27
+ def chain
28
+ ## note - default to mainnet if not set
29
+ self.chain = 'mainnet' unless defined?( @chain )
30
+ @chain
31
+ end
32
+
33
+ ## note: read-only for now - why? why not?
34
+ def client
35
+ ## note - default to btc/ if not set
36
+ self.chain = 'mainnet' unless defined?( @client )
37
+ @client
38
+ end
39
+
40
+ def delay_in_s
41
+ ## note - default to 1 (sec) if not set
42
+ self.delay_in_s = 1 unless defined?( @delay_in_s )
43
+ @delay_in_s
44
+ end
45
+ def delay_in_s=(value) @delay_in_s = value; end
46
+ alias_method :sleep, :delay_in_s ## add sleep alias (or wait) - why? why not?
47
+ alias_method :sleep=, :delay_in_s=
48
+ end # class Configuration
49
+
50
+
51
+ ## lets you use
52
+ ## Ordinals.configure do |config|
53
+ ## config.chain = :btc
54
+ ## end
55
+ def self.configure() yield( config ); end
56
+ def self.config() @config ||= Configuration.new; end
57
+
58
+ ## add some convenience shortcut helpers (no config. required) - why? why not?
59
+ def self.client() config.client; end
60
+ def self.chain() config.chain; end
61
+ def self.chain=(value) config.chain = value; end
62
+
63
+
64
+ def self.mainnet?() config.chain == 'mainnet'; end
65
+ def self.goerli?() config.chain == 'goerli'; end
66
+
67
+
68
+ ###################
69
+ ### more convenience shortcuts
70
+
71
+ def self.inscribes( **kwargs ) client.ethscriptions( **kwargs ); end
72
+ def self.inscribe( id_or_num ) client.ethscription( id_or_num ); end
73
+ end # module Ethscribe
74
+
75
+
76
+
77
+
78
+ ## our own code
79
+ require_relative 'ethscribe/version'
80
+ require_relative 'ethscribe/api'
81
+
82
+
83
+
84
+ module Ethscribe
85
+ #############
86
+ ## add more convenience alias - why? why not?
87
+ API = Api
88
+ end # module Ethscribe
89
+
90
+
91
+
92
+ # say hello
93
+ puts Ethscribe.banner ## if defined?($RUBYCOCOS_DEBUG) && $RUBCOCOS_DEBUG
3
94
 
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ethscribe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-20 00:00:00.000000000 Z
11
+ date: 2023-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cocos
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: rdoc
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,8 +58,8 @@ dependencies:
44
58
  - - "~>"
45
59
  - !ruby/object:Gem::Version
46
60
  version: '4.0'
47
- description: ethscribe - inscription (ethscription calldata) api wrapper & helpers
48
- for Ethereum & co.
61
+ description: ethscribe - inscription / inscribe (ethscription calldata) api wrapper
62
+ & helpers for Ethereum & co.
49
63
  email: gerald.bauer@gmail.com
50
64
  executables: []
51
65
  extensions: []
@@ -59,6 +73,8 @@ files:
59
73
  - README.md
60
74
  - Rakefile
61
75
  - lib/ethscribe.rb
76
+ - lib/ethscribe/api.rb
77
+ - lib/ethscribe/version.rb
62
78
  homepage: https://github.com/s6ruby/rubidity
63
79
  licenses:
64
80
  - Public Domain
@@ -83,6 +99,6 @@ requirements: []
83
99
  rubygems_version: 3.4.10
84
100
  signing_key:
85
101
  specification_version: 4
86
- summary: ethscribe - inscription (ethscription calldata) api wrapper & helpers for
87
- Ethereum & co.
102
+ summary: ethscribe - inscription / inscribe (ethscription calldata) api wrapper &
103
+ helpers for Ethereum & co.
88
104
  test_files: []