Skip to content

Commit

Permalink
feat: Implement Circle Web3 Services Ruby Client
Browse files Browse the repository at this point in the history
- Add basic API client with Faraday for HTTP requests
- Implement wallet sets API endpoints (get/create)
- Add configuration system with entity secret encryption
- Add response handling and error types
- Add documentation with usage examples

Key features:
- Automatic entity secret ciphertext generation
- Structured API responses
- Error handling for API calls
- Sandbox environment support
  • Loading branch information
Madao-3 committed Oct 31, 2024
1 parent 02a3b2f commit 4fc3785
Show file tree
Hide file tree
Showing 20 changed files with 1,117 additions and 526 deletions.
123 changes: 123 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
PATH
remote: .
specs:
circle-w3s (0.1.0)
eth (~> 0.5.9)
faraday (~> 2.0)
json (~> 2.0)
jwt (~> 2.7)

GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
base64 (0.2.0)
diff-lcs (1.5.1)
dotenv (3.1.4)
eth (0.5.12)
forwardable (~> 1.3)
keccak (~> 1.3)
konstructor (~> 1.0)
openssl (>= 2.2, < 4.0)
rbsecp256k1 (~> 6.0)
scrypt (~> 3.0)
faraday (2.12.0)
faraday-net_http (>= 2.0, < 3.4)
json
logger
faraday-net_http (3.3.0)
net-http
ffi (1.17.0)
ffi (1.17.0-aarch64-linux-gnu)
ffi (1.17.0-aarch64-linux-musl)
ffi (1.17.0-arm-linux-gnu)
ffi (1.17.0-arm-linux-musl)
ffi (1.17.0-arm64-darwin)
ffi (1.17.0-x86-linux-gnu)
ffi (1.17.0-x86-linux-musl)
ffi (1.17.0-x86_64-darwin)
ffi (1.17.0-x86_64-linux-gnu)
ffi (1.17.0-x86_64-linux-musl)
ffi-compiler (1.3.2)
ffi (>= 1.15.5)
rake
forwardable (1.3.3)
json (2.7.5)
jwt (2.9.3)
base64
keccak (1.3.1)
konstructor (1.0.2)
language_server-protocol (3.17.0.3)
logger (1.6.1)
mini_portile2 (2.8.7)
net-http (0.4.1)
uri
openssl (3.2.0)
parallel (1.26.3)
parser (3.3.5.0)
ast (~> 2.4.1)
racc
pkg-config (1.5.7)
racc (1.8.1)
rainbow (3.1.1)
rake (13.2.1)
rbsecp256k1 (6.0.0)
mini_portile2 (~> 2.8)
pkg-config (~> 1.5)
rubyzip (~> 2.3)
regexp_parser (2.9.2)
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.2)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-support (3.13.1)
rubocop (1.68.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.4, < 3.0)
rubocop-ast (>= 1.32.2, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.33.0)
parser (>= 3.3.1.0)
ruby-progressbar (1.13.0)
rubyzip (2.3.2)
scrypt (3.0.8)
ffi-compiler (>= 1.0, < 2.0)
rake (>= 9, < 14)
unicode-display_width (2.6.0)
uri (0.13.1)

PLATFORMS
aarch64-linux-gnu
aarch64-linux-musl
arm-linux-gnu
arm-linux-musl
arm64-darwin
ruby
x86-linux-gnu
x86-linux-musl
x86_64-darwin
x86_64-linux-gnu
x86_64-linux-musl

DEPENDENCIES
circle-w3s!
dotenv
rake (~> 13.0)
rspec (~> 3.0)
rubocop (~> 1.21)

BUNDLED WITH
2.5.20
88 changes: 67 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,89 @@
# CircleW3s
# Circle Web3 Services Ruby Client

TODO: Delete this and the text below, and describe your gem

Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/circle-w3s`. To experiment with that code, run `bin/console` for an interactive prompt.
Ruby client for Circle's Web3 Services API.

## Installation

TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.

Install the gem and add to the application's Gemfile by executing:
Add this line to your application's Gemfile:
```ruby
gem "circle-w3s-ruby"
```

And then execute:
```bash
bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
bundle install
```

If bundler is not being used to manage dependencies, install the gem by executing:

Or install it yourself as:
```bash
gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
gem install circle-w3s-ruby
```

## Usage

TODO: Write usage instructions here
### Configuration

First, configure the client with your API credentials:

```ruby
CircleW3s.configure do |config|
config.access_token = "TEST_API_KEY:your-key-id:your-key-secret"
config.host = "https://api-sandbox.circle.com"
config.entity_secret = "your-entity-secret" # 32-byte hex string
end
```

## Development
### Examples

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
#### List Wallet Sets

To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
```ruby
# Create API client
client = CircleW3s::ApiClient.new(CircleW3s.configuration)
wallet_sets_api = CircleW3s::WalletSetsApi.new(client)

## Contributing
# Get wallet sets
response = wallet_sets_api.get_wallet_sets
puts response.data # Access the wallet sets data
```

#### Create Wallet Set

```ruby
# Create API client
client = CircleW3s::ApiClient.new(CircleW3s.configuration)
wallet_sets_api = CircleW3s::WalletSetsApi.new(client)

# Create request with automatically generated entity_secret_ciphertext
request = CircleW3s::CreateWalletSetRequest.new(
name: "My First Wallet Set",
entity_secret_ciphertext: CircleW3s.configuration.generate_entity_secret_ciphertext
)

# Create wallet set
response = wallet_sets_api.create_wallet_set(request)
puts response.data # Access the created wallet set data
```

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/circle-w3s. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/circle-w3s/blob/main/CODE_OF_CONDUCT.md).
## Response Structure

## License
All API responses are wrapped in a structured object with the following attributes:
- `data`: The actual response data
- `success`: Boolean indicating if the request was successful
- `status`: HTTP status code

The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
## Error Handling

## Code of Conduct
The client will raise exceptions for various error cases:
- `CircleW3s::UnauthorizedError`: 401 authentication errors
- `CircleW3s::ApiError`: Other API errors

Everyone interacting in the CircleW3s project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/circle-w3s/blob/main/CODE_OF_CONDUCT.md).
```ruby
begin
response = wallet_sets_api.get_wallet_sets
rescue CircleW3s::UnauthorizedError => e
puts "Authentication failed: #{e.message}"
rescue CircleW3s::ApiError => e
puts "API error: #{e.message}"
end
```
Binary file modified circle-w3s-0.1.0.gem
Binary file not shown.
4 changes: 2 additions & 2 deletions circle-w3s.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ Gem::Specification.new do |spec|
spec.add_dependency "eth", "~> 0.5.9"
spec.add_dependency "jwt", "~> 2.7"

spec.add_development_dependency "rspec", "~> 3.0"
spec.add_development_dependency "dotenv", "~> 2.7"
spec.add_development_dependency "rspec"
spec.add_development_dependency "dotenv"
end
55 changes: 25 additions & 30 deletions lib/circle-w3s.rb
Original file line number Diff line number Diff line change
@@ -1,38 +1,33 @@
require "faraday"
require "json"
require "eth"
require "jwt"

require_relative "circle-w3s/version"
require_relative "circle-w3s/configuration"
require_relative "circle-w3s/client"
require_relative "circle-w3s/errors/api_error"

# Resources
require_relative "circle-w3s/resources/wallets"
require_relative "circle-w3s/resources/transactions"
require_relative "circle-w3s/resources/user_tokens"
require_relative "circle-w3s/resources/challenge_ids"
require_relative "circle-w3s/resources/security_questions"
require_relative "circle-w3s/resources/pin_codes"
require 'circle-w3s/version'
require 'circle-w3s/configuration'
require 'circle-w3s/api_client'
require 'circle-w3s/api/wallets_api'
require 'circle-w3s/api/wallet_sets_api'
require 'circle-w3s/api/transactions_api'
require "circle-w3s/models/wallet"
require "circle-w3s/models/wallet_set"
require "circle-w3s/models/transaction"
require "circle-w3s/models/create_wallet_request"
require "circle-w3s/models/create_wallet_set_request"

module CircleW3s
class Error < StandardError; end

class << self
attr_accessor :configuration
end
class ApiError < Error; end
class UnauthorizedError < ApiError; end
class NotFoundError < ApiError; end
class BadRequestError < ApiError; end

def self.configure
self.configuration ||= Configuration.new
yield(configuration) if block_given?
end
class << self
def configuration
@configuration ||= Configuration.new
end

def self.reset
self.configuration = Configuration.new
end
def configure
yield(configuration) if block_given?
end

def self.client
@client ||= Client.new(configuration)
def reset
@configuration = Configuration.new
end
end
end
60 changes: 60 additions & 0 deletions lib/circle-w3s/api/signing_api.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module CircleW3s
class SigningApi
attr_reader :api_client

def initialize(api_client = ApiClient.default)
@api_client = api_client
end

# Sign message
# @param sign_message_request [SignMessageRequest] Request body for signing a message
# @return [SignatureResponse]
def sign_message(sign_message_request)
api_client.fill_entity_secret_ciphertext(sign_message_request)
api_client.fill_idempotency_key(sign_message_request)

response = api_client.call_api(
path: '/v1/w3s/developer/sign/message',
http_method: :post,
body: sign_message_request,
auth_names: ['BearerAuth'],
return_type: 'SignatureResponse'
)
response.data
end

# Sign transaction
# @param sign_transaction_request [SignTransactionRequest] Request body for signing a transaction
# @return [SignTransactionResponse]
def sign_transaction(sign_transaction_request)
api_client.fill_entity_secret_ciphertext(sign_transaction_request)
api_client.fill_idempotency_key(sign_transaction_request)

response = api_client.call_api(
path: '/v1/w3s/developer/sign/transaction',
http_method: :post,
body: sign_transaction_request,
auth_names: ['BearerAuth'],
return_type: 'SignTransactionResponse'
)
response.data
end

# Sign typed data
# @param sign_typed_data_request [SignTypedDataRequest] Request body for signing typed data
# @return [SignatureResponse]
def sign_typed_data(sign_typed_data_request)
api_client.fill_entity_secret_ciphertext(sign_typed_data_request)
api_client.fill_idempotency_key(sign_typed_data_request)

response = api_client.call_api(
path: '/v1/w3s/developer/sign/typedData',
http_method: :post,
body: sign_typed_data_request,
auth_names: ['BearerAuth'],
return_type: 'SignatureResponse'
)
response.data
end
end
end
Loading

0 comments on commit 4fc3785

Please sign in to comment.