ethscribe 0.0.1 → 0.2.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: 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: []