anvil-ruby 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/AGENTS.md +123 -0
- data/API_COVERAGE.md +294 -0
- data/CHANGELOG.md +34 -0
- data/CLAUDE_README.md +98 -0
- data/GITHUB_ACTIONS_QUICKREF.md +174 -0
- data/Gemfile.lock +112 -0
- data/Gemfile.minimal +9 -0
- data/LICENSE +21 -0
- data/PROJECT_CONTEXT.md +196 -0
- data/README.md +445 -0
- data/anvil-ruby.gemspec +66 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/create_signature_direct.rb +142 -0
- data/create_signature_packet.rb +232 -0
- data/debug_env.rb +28 -0
- data/examples/create_signature.rb +194 -0
- data/examples/fill_pdf.rb +89 -0
- data/examples/generate_pdf.rb +347 -0
- data/examples/verify_webhook.rb +281 -0
- data/lib/anvil/client.rb +216 -0
- data/lib/anvil/configuration.rb +87 -0
- data/lib/anvil/env_loader.rb +30 -0
- data/lib/anvil/errors.rb +95 -0
- data/lib/anvil/rate_limiter.rb +66 -0
- data/lib/anvil/resources/base.rb +100 -0
- data/lib/anvil/resources/pdf.rb +171 -0
- data/lib/anvil/resources/signature.rb +517 -0
- data/lib/anvil/resources/webform.rb +154 -0
- data/lib/anvil/resources/webhook.rb +201 -0
- data/lib/anvil/resources/workflow.rb +169 -0
- data/lib/anvil/response.rb +98 -0
- data/lib/anvil/version.rb +5 -0
- data/lib/anvil.rb +88 -0
- data/quickstart_signature.rb +220 -0
- data/test_api_connection.rb +143 -0
- data/test_etch_signature.rb +230 -0
- data/test_gem.rb +72 -0
- data/test_signature.rb +281 -0
- data/test_signature_with_template.rb +112 -0
- metadata +247 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Anvil E-Signature Quickstart
|
|
5
|
+
# Based on: https://www.useanvil.com/docs/api/e-signatures
|
|
6
|
+
|
|
7
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
|
8
|
+
require 'anvil'
|
|
9
|
+
require 'anvil/env_loader'
|
|
10
|
+
|
|
11
|
+
# Load .env file
|
|
12
|
+
Anvil::EnvLoader.load(File.expand_path('.env', __dir__))
|
|
13
|
+
|
|
14
|
+
# Configure Anvil
|
|
15
|
+
Anvil.configure do |config|
|
|
16
|
+
config.api_key = ENV.fetch('ANVIL_API_KEY', nil)
|
|
17
|
+
config.environment = :development
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
puts '=' * 50
|
|
21
|
+
puts 'Anvil E-Signature Quickstart'
|
|
22
|
+
puts '=' * 50
|
|
23
|
+
puts "\nUsing API Key: #{ENV.fetch('ANVIL_API_KEY', nil)[0..10]}..."
|
|
24
|
+
|
|
25
|
+
# Since the Signature class uses GraphQL, we need to test it differently
|
|
26
|
+
# Let's create a test packet using the REST API directly
|
|
27
|
+
|
|
28
|
+
def create_test_etch_packet
|
|
29
|
+
puts "\nš Creating a test e-signature packet..."
|
|
30
|
+
|
|
31
|
+
client = Anvil::Client.new
|
|
32
|
+
|
|
33
|
+
# GraphQL mutation for creating an Etch packet
|
|
34
|
+
# Note: This creates a simple test packet without files
|
|
35
|
+
mutation = <<~GRAPHQL
|
|
36
|
+
mutation CreateEtchPacket {
|
|
37
|
+
createEtchPacket(
|
|
38
|
+
name: "Test Agreement - Ruby Gem #{Time.now.to_i}",
|
|
39
|
+
isDraft: false,
|
|
40
|
+
signers: [
|
|
41
|
+
{
|
|
42
|
+
name: "Test Signer 1",
|
|
43
|
+
email: "test1@example.com",
|
|
44
|
+
signerType: "email"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
) {
|
|
48
|
+
eid
|
|
49
|
+
name
|
|
50
|
+
status
|
|
51
|
+
createdAt
|
|
52
|
+
signers {
|
|
53
|
+
eid
|
|
54
|
+
name
|
|
55
|
+
email
|
|
56
|
+
status
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
GRAPHQL
|
|
61
|
+
|
|
62
|
+
begin
|
|
63
|
+
response = client.post('https://app.useanvil.com/graphql', {
|
|
64
|
+
query: mutation
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
if response.success?
|
|
68
|
+
data = response.data
|
|
69
|
+
if data[:data] && data[:data][:createEtchPacket]
|
|
70
|
+
packet = data[:data][:createEtchPacket]
|
|
71
|
+
|
|
72
|
+
puts 'ā
Signature packet created successfully!'
|
|
73
|
+
puts "\nš Packet Details:"
|
|
74
|
+
puts " EID: #{packet[:eid]}"
|
|
75
|
+
puts " Name: #{packet[:name]}"
|
|
76
|
+
puts " Status: #{packet[:status]}"
|
|
77
|
+
puts " Created: #{packet[:createdAt]}"
|
|
78
|
+
|
|
79
|
+
if packet[:signers]
|
|
80
|
+
puts "\nš„ Signers:"
|
|
81
|
+
packet[:signers].each do |signer|
|
|
82
|
+
puts " - #{signer[:name]} (#{signer[:email]})"
|
|
83
|
+
puts " Status: #{signer[:status]}"
|
|
84
|
+
puts " EID: #{signer[:eid]}"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Get signing URL
|
|
89
|
+
generate_signing_url(packet[:eid], packet[:signers].first[:eid])
|
|
90
|
+
|
|
91
|
+
packet
|
|
92
|
+
else
|
|
93
|
+
puts 'ā No packet data returned'
|
|
94
|
+
puts "Response: #{data.inspect}"
|
|
95
|
+
end
|
|
96
|
+
else
|
|
97
|
+
puts "ā Request failed: #{response.error_message}"
|
|
98
|
+
end
|
|
99
|
+
rescue StandardError => e
|
|
100
|
+
puts "ā Error: #{e.message}"
|
|
101
|
+
puts e.backtrace.first(5)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def generate_signing_url(packet_eid, signer_eid)
|
|
106
|
+
puts "\nš Generating signing URL..."
|
|
107
|
+
|
|
108
|
+
client = Anvil::Client.new
|
|
109
|
+
|
|
110
|
+
mutation = <<~GRAPHQL
|
|
111
|
+
mutation GenerateEtchSignURL {
|
|
112
|
+
generateEtchSignURL(
|
|
113
|
+
input: {
|
|
114
|
+
packetEid: "#{packet_eid}"
|
|
115
|
+
signerEid: "#{signer_eid}"
|
|
116
|
+
}
|
|
117
|
+
) {
|
|
118
|
+
url
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
GRAPHQL
|
|
122
|
+
|
|
123
|
+
begin
|
|
124
|
+
response = client.post('https://app.useanvil.com/graphql', {
|
|
125
|
+
query: mutation
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
if response.success?
|
|
129
|
+
data = response.data
|
|
130
|
+
if data[:data] && data[:data][:generateEtchSignURL]
|
|
131
|
+
url = data[:data][:generateEtchSignURL][:url]
|
|
132
|
+
puts 'ā
Signing URL generated:'
|
|
133
|
+
puts " #{url}"
|
|
134
|
+
puts "\nš§ Send this URL to the signer to collect their signature"
|
|
135
|
+
url
|
|
136
|
+
else
|
|
137
|
+
puts 'ā No URL returned'
|
|
138
|
+
end
|
|
139
|
+
else
|
|
140
|
+
puts "ā Failed to generate URL: #{response.error_message}"
|
|
141
|
+
end
|
|
142
|
+
rescue StandardError => e
|
|
143
|
+
puts "ā Error: #{e.message}"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def list_etch_packets
|
|
148
|
+
puts "\nš Listing your signature packets..."
|
|
149
|
+
|
|
150
|
+
client = Anvil::Client.new
|
|
151
|
+
|
|
152
|
+
query = <<~GRAPHQL
|
|
153
|
+
query ListEtchPackets {
|
|
154
|
+
etchPackets(limit: 5) {
|
|
155
|
+
eid
|
|
156
|
+
name
|
|
157
|
+
status
|
|
158
|
+
createdAt
|
|
159
|
+
completedAt
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
GRAPHQL
|
|
163
|
+
|
|
164
|
+
begin
|
|
165
|
+
response = client.post('https://app.useanvil.com/graphql', {
|
|
166
|
+
query: query
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
if response.success?
|
|
170
|
+
data = response.data
|
|
171
|
+
if data[:data] && data[:data][:etchPackets]
|
|
172
|
+
packets = data[:data][:etchPackets]
|
|
173
|
+
|
|
174
|
+
if packets.empty?
|
|
175
|
+
puts 'No signature packets found'
|
|
176
|
+
else
|
|
177
|
+
puts "Found #{packets.length} packet(s):"
|
|
178
|
+
packets.each do |packet|
|
|
179
|
+
puts "\n š #{packet[:name]}"
|
|
180
|
+
puts " EID: #{packet[:eid]}"
|
|
181
|
+
puts " Status: #{packet[:status]}"
|
|
182
|
+
puts " Created: #{packet[:createdAt]}"
|
|
183
|
+
puts " Completed: #{packet[:completedAt] || 'Not yet'}"
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
else
|
|
188
|
+
puts "ā Failed to list packets: #{response.error_message}"
|
|
189
|
+
end
|
|
190
|
+
rescue StandardError => e
|
|
191
|
+
puts "ā Error: #{e.message}"
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Main execution
|
|
196
|
+
puts "\nš Testing Anvil E-Signature API..."
|
|
197
|
+
|
|
198
|
+
# List existing packets
|
|
199
|
+
list_etch_packets
|
|
200
|
+
|
|
201
|
+
# Create a new test packet
|
|
202
|
+
create_test_etch_packet
|
|
203
|
+
|
|
204
|
+
puts "\n#{'=' * 50}"
|
|
205
|
+
puts 'ā
E-Signature API test complete!'
|
|
206
|
+
puts '=' * 50
|
|
207
|
+
|
|
208
|
+
puts "\nš What just happened:"
|
|
209
|
+
puts '1. Created a signature packet with the Anvil API'
|
|
210
|
+
puts '2. Added a test signer'
|
|
211
|
+
puts '3. Generated a signing URL'
|
|
212
|
+
|
|
213
|
+
puts "\nš” Next steps:"
|
|
214
|
+
puts '1. The signer would receive the URL via email (in production)'
|
|
215
|
+
puts '2. They click the link and sign the document'
|
|
216
|
+
puts '3. You receive a webhook when complete'
|
|
217
|
+
puts '4. You can download the signed document'
|
|
218
|
+
|
|
219
|
+
puts "\nš Learn more:"
|
|
220
|
+
puts ' https://www.useanvil.com/docs/api/e-signatures'
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Test Anvil API connection and endpoints
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
|
7
|
+
require 'anvil'
|
|
8
|
+
require 'anvil/env_loader'
|
|
9
|
+
require 'net/http'
|
|
10
|
+
require 'uri'
|
|
11
|
+
require 'json'
|
|
12
|
+
|
|
13
|
+
# Load .env file
|
|
14
|
+
Anvil::EnvLoader.load(File.expand_path('.env', __dir__))
|
|
15
|
+
|
|
16
|
+
puts '=' * 50
|
|
17
|
+
puts 'Anvil API Connection Test'
|
|
18
|
+
puts '=' * 50
|
|
19
|
+
|
|
20
|
+
api_key = ENV.fetch('ANVIL_API_KEY', nil)
|
|
21
|
+
puts "\nUsing API Key: #{api_key[0..10]}..."
|
|
22
|
+
|
|
23
|
+
# Test 1: Direct REST API call (we know this works)
|
|
24
|
+
def test_rest_api(api_key)
|
|
25
|
+
puts "\n1ļøā£ Testing REST API (PDF Generation)..."
|
|
26
|
+
|
|
27
|
+
uri = URI('https://app.useanvil.com/api/v1/generate-pdf')
|
|
28
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
29
|
+
http.use_ssl = true
|
|
30
|
+
|
|
31
|
+
request = Net::HTTP::Post.new(uri.path)
|
|
32
|
+
request.basic_auth(api_key, '')
|
|
33
|
+
request['Content-Type'] = 'application/json'
|
|
34
|
+
request.body = {
|
|
35
|
+
type: 'markdown',
|
|
36
|
+
data: [{ content: '# Test\nThis is a test.' }]
|
|
37
|
+
}.to_json
|
|
38
|
+
|
|
39
|
+
response = http.request(request)
|
|
40
|
+
|
|
41
|
+
if response.code == '200'
|
|
42
|
+
puts ' ā
REST API works! (PDF generated)'
|
|
43
|
+
true
|
|
44
|
+
else
|
|
45
|
+
puts " ā REST API failed: #{response.code}"
|
|
46
|
+
puts " Response: #{response.body[0..200]}"
|
|
47
|
+
false
|
|
48
|
+
end
|
|
49
|
+
rescue StandardError => e
|
|
50
|
+
puts " ā Error: #{e.message}"
|
|
51
|
+
false
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Test 2: GraphQL API
|
|
55
|
+
def test_graphql_api(api_key)
|
|
56
|
+
puts "\n2ļøā£ Testing GraphQL API..."
|
|
57
|
+
|
|
58
|
+
uri = URI('https://app.useanvil.com/graphql')
|
|
59
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
60
|
+
http.use_ssl = true
|
|
61
|
+
|
|
62
|
+
request = Net::HTTP::Post.new(uri.path)
|
|
63
|
+
request.basic_auth(api_key, '')
|
|
64
|
+
request['Content-Type'] = 'application/json'
|
|
65
|
+
|
|
66
|
+
# Simple query to test GraphQL
|
|
67
|
+
query = {
|
|
68
|
+
query: <<~GRAPHQL
|
|
69
|
+
query {
|
|
70
|
+
currentUser {
|
|
71
|
+
eid
|
|
72
|
+
name
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
GRAPHQL
|
|
76
|
+
}.to_json
|
|
77
|
+
|
|
78
|
+
request.body = query
|
|
79
|
+
|
|
80
|
+
response = http.request(request)
|
|
81
|
+
|
|
82
|
+
if response.code == '200'
|
|
83
|
+
data = JSON.parse(response.body)
|
|
84
|
+
if data['data']
|
|
85
|
+
puts ' ā
GraphQL API works!'
|
|
86
|
+
puts " User: #{data['data']['currentUser']}"
|
|
87
|
+
true
|
|
88
|
+
else
|
|
89
|
+
puts ' ā ļø GraphQL responded but no data'
|
|
90
|
+
puts " Response: #{response.body[0..200]}"
|
|
91
|
+
false
|
|
92
|
+
end
|
|
93
|
+
else
|
|
94
|
+
puts " ā GraphQL API failed: #{response.code}"
|
|
95
|
+
puts " Response: #{response.body[0..200]}"
|
|
96
|
+
false
|
|
97
|
+
end
|
|
98
|
+
rescue StandardError => e
|
|
99
|
+
puts " ā Error: #{e.message}"
|
|
100
|
+
false
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Test 3: Using the Ruby gem client
|
|
104
|
+
def test_gem_client(api_key)
|
|
105
|
+
puts "\n3ļøā£ Testing Ruby Gem Client..."
|
|
106
|
+
|
|
107
|
+
Anvil.configure do |config|
|
|
108
|
+
config.api_key = api_key
|
|
109
|
+
config.environment = :development
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Test PDF generation (we know this works)
|
|
113
|
+
Anvil::PDF.generate_from_markdown('# Test Document')
|
|
114
|
+
puts ' ā
Gem client works! (PDF generated)'
|
|
115
|
+
true
|
|
116
|
+
rescue StandardError => e
|
|
117
|
+
puts " ā Gem client error: #{e.message}"
|
|
118
|
+
false
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Run all tests
|
|
122
|
+
rest_ok = test_rest_api(api_key)
|
|
123
|
+
graphql_ok = test_graphql_api(api_key)
|
|
124
|
+
gem_ok = test_gem_client(api_key)
|
|
125
|
+
|
|
126
|
+
puts "\n#{'=' * 50}"
|
|
127
|
+
puts 'Test Results:'
|
|
128
|
+
puts '=' * 50
|
|
129
|
+
puts "REST API: #{rest_ok ? 'ā
' : 'ā'}"
|
|
130
|
+
puts "GraphQL API: #{graphql_ok ? 'ā
' : 'ā'}"
|
|
131
|
+
puts "Ruby Gem: #{gem_ok ? 'ā
' : 'ā'}"
|
|
132
|
+
|
|
133
|
+
if graphql_ok
|
|
134
|
+
puts "\nā
GraphQL is working! We can proceed with e-signatures."
|
|
135
|
+
else
|
|
136
|
+
puts "\nā ļø GraphQL is not working. E-signatures require GraphQL."
|
|
137
|
+
puts "\nPossible issues:"
|
|
138
|
+
puts '1. GraphQL might require a different authentication method'
|
|
139
|
+
puts '2. The endpoint might be different'
|
|
140
|
+
puts '3. Your account might not have GraphQL access'
|
|
141
|
+
puts "\nš” Try the REST API e-signature endpoints instead:"
|
|
142
|
+
puts ' POST https://app.useanvil.com/api/v1/etch-packets'
|
|
143
|
+
end
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Create an Anvil Etch E-Signature Packet
|
|
5
|
+
# Using the correct GraphQL endpoint and mutation structure
|
|
6
|
+
|
|
7
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
|
8
|
+
require 'anvil'
|
|
9
|
+
require 'anvil/env_loader'
|
|
10
|
+
require 'net/http'
|
|
11
|
+
require 'uri'
|
|
12
|
+
require 'json'
|
|
13
|
+
|
|
14
|
+
# Load .env file
|
|
15
|
+
Anvil::EnvLoader.load(File.expand_path('.env', __dir__))
|
|
16
|
+
|
|
17
|
+
puts '=' * 50
|
|
18
|
+
puts 'šļø Anvil Etch E-Signature Test'
|
|
19
|
+
puts '=' * 50
|
|
20
|
+
|
|
21
|
+
api_key = ENV.fetch('ANVIL_API_KEY', nil)
|
|
22
|
+
puts "\nUsing API Key: #{api_key[0..10]}..."
|
|
23
|
+
|
|
24
|
+
# Test 1: Basic GraphQL query to verify connection
|
|
25
|
+
def test_graphql_connection(api_key)
|
|
26
|
+
puts "\n1ļøā£ Testing GraphQL connection..."
|
|
27
|
+
|
|
28
|
+
uri = URI('https://graphql.useanvil.com/')
|
|
29
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
30
|
+
http.use_ssl = true
|
|
31
|
+
|
|
32
|
+
request = Net::HTTP::Post.new(uri.path || '/')
|
|
33
|
+
request.basic_auth(api_key, '')
|
|
34
|
+
request['Content-Type'] = 'application/json'
|
|
35
|
+
|
|
36
|
+
query = {
|
|
37
|
+
query: <<~GRAPHQL
|
|
38
|
+
query {
|
|
39
|
+
currentUser {
|
|
40
|
+
eid
|
|
41
|
+
name
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
GRAPHQL
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
request.body = query.to_json
|
|
48
|
+
response = http.request(request)
|
|
49
|
+
|
|
50
|
+
if response.code == '200'
|
|
51
|
+
data = JSON.parse(response.body)
|
|
52
|
+
if data['data']
|
|
53
|
+
puts ' ā
GraphQL connection works!'
|
|
54
|
+
puts " User: #{data['data']['currentUser']}"
|
|
55
|
+
return true
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
puts " ā GraphQL connection failed: #{response.code}"
|
|
60
|
+
puts " Response: #{response.body[0..200]}"
|
|
61
|
+
false
|
|
62
|
+
rescue StandardError => e
|
|
63
|
+
puts " ā Error: #{e.message}"
|
|
64
|
+
false
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Test 2: Create a simple Etch packet (without a template for now)
|
|
68
|
+
def create_simple_etch_packet(api_key)
|
|
69
|
+
puts "\n2ļøā£ Creating a simple Etch packet..."
|
|
70
|
+
|
|
71
|
+
uri = URI('https://graphql.useanvil.com/')
|
|
72
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
73
|
+
http.use_ssl = true
|
|
74
|
+
|
|
75
|
+
request = Net::HTTP::Post.new(uri.path || '/')
|
|
76
|
+
request.basic_auth(api_key, '')
|
|
77
|
+
request['Content-Type'] = 'application/json'
|
|
78
|
+
|
|
79
|
+
# Simple mutation - create a draft packet
|
|
80
|
+
mutation = {
|
|
81
|
+
query: <<~GRAPHQL
|
|
82
|
+
mutation CreateTestPacket {
|
|
83
|
+
createEtchPacket(
|
|
84
|
+
name: "Test Signature Packet #{Time.now.to_i}"
|
|
85
|
+
isDraft: true
|
|
86
|
+
isTest: true
|
|
87
|
+
signers: [
|
|
88
|
+
{
|
|
89
|
+
id: "signer1"
|
|
90
|
+
name: "Test Signer"
|
|
91
|
+
email: "test@example.com"
|
|
92
|
+
signerType: "email"
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
) {
|
|
96
|
+
eid
|
|
97
|
+
name
|
|
98
|
+
status
|
|
99
|
+
createdAt
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
GRAPHQL
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
request.body = mutation.to_json
|
|
106
|
+
response = http.request(request)
|
|
107
|
+
result = JSON.parse(response.body)
|
|
108
|
+
|
|
109
|
+
if response.code == '200'
|
|
110
|
+
if result['data'] && result['data']['createEtchPacket']
|
|
111
|
+
packet = result['data']['createEtchPacket']
|
|
112
|
+
puts ' ā
Etch packet created!'
|
|
113
|
+
puts " EID: #{packet['eid']}"
|
|
114
|
+
puts " Name: #{packet['name']}"
|
|
115
|
+
puts " Status: #{packet['status']}"
|
|
116
|
+
return packet
|
|
117
|
+
elsif result['errors']
|
|
118
|
+
puts ' ā GraphQL errors:'
|
|
119
|
+
result['errors'].each do |error|
|
|
120
|
+
puts " - #{error['message']}"
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
else
|
|
124
|
+
puts " ā Request failed: #{response.code}"
|
|
125
|
+
puts " Response: #{result}"
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
nil
|
|
129
|
+
rescue StandardError => e
|
|
130
|
+
puts " ā Error: #{e.message}"
|
|
131
|
+
nil
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Test 3: List existing Etch packets
|
|
135
|
+
def list_etch_packets(api_key)
|
|
136
|
+
puts "\n3ļøā£ Listing existing Etch packets..."
|
|
137
|
+
|
|
138
|
+
uri = URI('https://graphql.useanvil.com/')
|
|
139
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
140
|
+
http.use_ssl = true
|
|
141
|
+
|
|
142
|
+
request = Net::HTTP::Post.new(uri.path || '/')
|
|
143
|
+
request.basic_auth(api_key, '')
|
|
144
|
+
request['Content-Type'] = 'application/json'
|
|
145
|
+
|
|
146
|
+
query = {
|
|
147
|
+
query: <<~GRAPHQL
|
|
148
|
+
query {
|
|
149
|
+
etchPackets(limit: 5) {
|
|
150
|
+
eid
|
|
151
|
+
name
|
|
152
|
+
status
|
|
153
|
+
createdAt
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
GRAPHQL
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
request.body = query.to_json
|
|
160
|
+
response = http.request(request)
|
|
161
|
+
|
|
162
|
+
if response.code == '200'
|
|
163
|
+
data = JSON.parse(response.body)
|
|
164
|
+
if data['data'] && data['data']['etchPackets']
|
|
165
|
+
packets = data['data']['etchPackets']
|
|
166
|
+
if packets.empty?
|
|
167
|
+
puts ' No Etch packets found'
|
|
168
|
+
else
|
|
169
|
+
puts " Found #{packets.length} packet(s):"
|
|
170
|
+
packets.each do |p|
|
|
171
|
+
puts " - #{p['name']} (#{p['status']})"
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
return true
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
puts ' ā Failed to list packets'
|
|
179
|
+
false
|
|
180
|
+
rescue StandardError => e
|
|
181
|
+
puts " ā Error: #{e.message}"
|
|
182
|
+
false
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Main execution
|
|
186
|
+
puts "\nš Starting Etch e-signature tests..."
|
|
187
|
+
|
|
188
|
+
# Test GraphQL connection
|
|
189
|
+
if test_graphql_connection(api_key)
|
|
190
|
+
# Try to list existing packets
|
|
191
|
+
list_etch_packets(api_key)
|
|
192
|
+
|
|
193
|
+
# Try to create a new packet
|
|
194
|
+
packet = create_simple_etch_packet(api_key)
|
|
195
|
+
|
|
196
|
+
if packet
|
|
197
|
+
puts "\n#{'=' * 50}"
|
|
198
|
+
puts 'ā
Success!'
|
|
199
|
+
puts '=' * 50
|
|
200
|
+
puts "\nYou've successfully created an Etch signature packet!"
|
|
201
|
+
puts "\nPacket ID: #{packet['eid']}"
|
|
202
|
+
puts "Status: #{packet['status']}"
|
|
203
|
+
|
|
204
|
+
puts "\nš Next steps:"
|
|
205
|
+
puts '1. Add a PDF template or upload a document'
|
|
206
|
+
puts '2. Configure signature fields'
|
|
207
|
+
puts '3. Send to signers'
|
|
208
|
+
puts '4. Track signature progress'
|
|
209
|
+
|
|
210
|
+
puts "\nš” To use with a PDF template:"
|
|
211
|
+
puts '1. Upload a PDF template at https://app.useanvil.com'
|
|
212
|
+
puts "2. Get the template's castEid"
|
|
213
|
+
puts '3. Include it in the createEtchPacket mutation:'
|
|
214
|
+
puts ' files: [{ id: "file1", castEid: "your_template_eid" }]'
|
|
215
|
+
else
|
|
216
|
+
puts "\nā ļø Couldn't create a packet, but connection works!"
|
|
217
|
+
puts "\nThis might be because:"
|
|
218
|
+
puts '1. Your account might require a PDF file/template'
|
|
219
|
+
puts '2. Additional fields might be required'
|
|
220
|
+
puts '3. Check the Anvil dashboard for more details'
|
|
221
|
+
end
|
|
222
|
+
else
|
|
223
|
+
puts "\nā GraphQL connection failed"
|
|
224
|
+
puts "\nPlease check:"
|
|
225
|
+
puts '1. Your API key is correct'
|
|
226
|
+
puts '2. Your account has API access enabled'
|
|
227
|
+
puts '3. The GraphQL endpoint is accessible'
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
puts "\nš Documentation: https://www.useanvil.com/docs/api/e-signatures"
|
data/test_gem.rb
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Quick test script for the Anvil gem
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path('lib', __dir__)
|
|
7
|
+
require 'anvil'
|
|
8
|
+
require 'anvil/env_loader'
|
|
9
|
+
|
|
10
|
+
# Load .env file
|
|
11
|
+
Anvil::EnvLoader.load(File.expand_path('.env', __dir__))
|
|
12
|
+
|
|
13
|
+
# Configure Anvil (will use ANVIL_API_KEY from .env file)
|
|
14
|
+
Anvil.configure do |config|
|
|
15
|
+
config.api_key = ENV['ANVIL_API_KEY'] || 'YOUR_API_KEY_HERE'
|
|
16
|
+
config.environment = :development
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
puts '=' * 50
|
|
20
|
+
puts 'Testing Anvil Ruby Gem'
|
|
21
|
+
puts '=' * 50
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
# Test 1: Generate a simple PDF from Markdown
|
|
25
|
+
puts "\nš Generating PDF from Markdown..."
|
|
26
|
+
|
|
27
|
+
pdf = Anvil::PDF.generate_from_markdown(<<~MD
|
|
28
|
+
# Anvil Ruby Test
|
|
29
|
+
|
|
30
|
+
This is a test of the Anvil Ruby gem!
|
|
31
|
+
|
|
32
|
+
## Features Working
|
|
33
|
+
|
|
34
|
+
- ā
API Configuration
|
|
35
|
+
- ā
PDF Generation
|
|
36
|
+
- ā
Zero dependencies
|
|
37
|
+
|
|
38
|
+
Generated at: #{Time.now}
|
|
39
|
+
MD
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
filename = "test_output_#{Time.now.to_i}.pdf"
|
|
43
|
+
pdf.save_as(filename)
|
|
44
|
+
|
|
45
|
+
puts "ā
Success! PDF saved as: #{filename}"
|
|
46
|
+
puts "š Size: #{pdf.size_human}"
|
|
47
|
+
|
|
48
|
+
# Test 2: Generate from HTML
|
|
49
|
+
puts "\nš Generating PDF from HTML..."
|
|
50
|
+
|
|
51
|
+
pdf2 = Anvil::PDF.generate_from_html(
|
|
52
|
+
html: '<h1>Hello from Ruby!</h1><p>The Anvil gem is working!</p>',
|
|
53
|
+
css: 'h1 { color: #007bff; }',
|
|
54
|
+
title: 'Test PDF'
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
filename2 = "test_html_#{Time.now.to_i}.pdf"
|
|
58
|
+
pdf2.save_as(filename2)
|
|
59
|
+
|
|
60
|
+
puts "ā
Success! HTML PDF saved as: #{filename2}"
|
|
61
|
+
puts "š Size: #{pdf2.size_human}"
|
|
62
|
+
|
|
63
|
+
puts "\nš All tests passed! Your Anvil Ruby gem is working!"
|
|
64
|
+
rescue Anvil::AuthenticationError => e
|
|
65
|
+
puts "ā Authentication failed: #{e.message}"
|
|
66
|
+
puts 'Please check your API key above'
|
|
67
|
+
rescue Anvil::Error => e
|
|
68
|
+
puts "ā Anvil error: #{e.message}"
|
|
69
|
+
rescue StandardError => e
|
|
70
|
+
puts "ā Error: #{e.message}"
|
|
71
|
+
puts e.backtrace.first(3)
|
|
72
|
+
end
|