Ruby SDK for GasFree.io - TRC-20 gasless transfer solution.
If you encounter any issues, feel free to open a discussion or report a bug via the GitHub Issues page.
You can also hire me as an external consultant if you need help integrating or customizing the gem for your project.
If you find this gem useful and want to support further development, you're welcome to donate here.
This gem is published on RubyGems.org.
Add this line to your application's Gemfile:
gem 'gasfree_sdk'And then execute:
$ bundle install
Or install it yourself as:
$ gem install gasfree_sdk
require 'gasfree_sdk'
GasfreeSdk.configure do |config|
config.api_key = "your-api-key"
config.api_secret = "your-api-secret"
config.api_endpoint = "https://open.gasfree.io/tron/" # TRON endpoint
end
# Note: The api_endpoint must be a valid http or https URL. If an invalid value is provided,
# a GasfreeSdk::Error will be raised during configuration.client = GasfreeSdk.clienttokens = client.tokens
tokens.each do |token|
puts "#{token.symbol} (#{token.token_address})"
puts " Activation Fee: #{token.activate_fee}"
puts " Transfer Fee: #{token.transfer_fee}"
endproviders = client.providers
providers.each do |provider|
puts "#{provider.name} (#{provider.address})"
puts " Max Pending Transfers: #{provider.config.max_pending_transfer}"
puts " Default Deadline: #{provider.config.default_deadline_duration}s"
endaccount = client.address("TYourTronAddress")
puts "GasFree Address: #{account.gas_free_address}"
puts "Active: #{account.active}"
puts "Nonce: #{account.nonce}"
account.assets.each do |asset|
puts "#{asset.token_symbol}: #{asset.frozen} frozen"
endThe SDK includes a comprehensive EIP-712 signature implementation specifically designed for TRON GasFree transfers. This module handles the complex cryptographic operations required for signing structured data according to the EIP-712 standard as implemented by TRON (TIP-712).
- Complete EIP-712 Implementation: Full support for EIP-712 structured data signing
- TRON-Specific Adaptations: Handles TRON address encoding and TIP-712 specifications
- Dual Network Support: Separate configurations for TRON Mainnet and Testnet (Nile)
- Flexible Key Handling: Support for multiple data key formats (camelCase, snake_case)
- Built-in Cryptography: Includes Keccak256 hashing and Base58 encoding for TRON addresses
# Example message data
message_data = {
token: "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", # USDT TRC-20
serviceProvider: "TGzz8gjYiYRqpfmDwnLxfgPuLVNmpCswVp",
user: "TYRhsi1fkke2tjdVW9XGYLjf8TgbbutEgY",
receiver: "TW1dWXfta5ygVN298JBN2UPhaSAUzo2owZ",
value: "3000000", # 3 USDT (6 decimals)
maxFee: "2000000", # 2 USDT max fee
deadline: (Time.now.to_i + 300).to_s, # 5 minutes from now
version: 1,
nonce: 0
}
private_key = "your_private_key_hex"
# Sign for TRON Testnet (Nile)
testnet_signature = GasfreeSdk::TronEIP712Signer.sign_typed_data_testnet(private_key, message_data)
# Sign for TRON Mainnet
mainnet_signature = GasfreeSdk::TronEIP712Signer.sign_typed_data_mainnet(private_key, message_data)
# Generic signing with custom domain
signature = GasfreeSdk::TronEIP712Signer.sign_typed_data(
private_key,
message_data,
domain: GasfreeSdk::TronEIP712Signer::DOMAIN_TESTNET
)custom_domain = {
name: "GasFreeController",
version: "V1.0.0",
chainId: 728_126_428,
verifyingContract: "THQGuFzL87ZqhxkgqYEryRAd7gqFqL5rdc"
}
signature = GasfreeSdk::TronEIP712Signer.sign_typed_data(
private_key,
message_data,
domain: custom_domain,
use_ethereum_v: true
)# Keccak256 hashing
hash = GasfreeSdk::TronEIP712Signer.keccac256("data to hash")
hex_hash = GasfreeSdk::TronEIP712Signer.keccac256_hex("data to hash")
# EIP-712 type encoding
encoded_type = GasfreeSdk::TronEIP712Signer.encode_type(:PermitTransfer)
# Structured data hashing
message_hash = GasfreeSdk::TronEIP712Signer.hash_struct(:PermitTransfer, message_data)
domain_hash = GasfreeSdk::TronEIP712Signer.hash_domain# Base58 encoding/decoding for TRON addresses
binary_data = GasfreeSdk::Base58.base58_to_binary("TYRhsi1fkke2tjdVW9XGYLjf8TgbbutEgY")
base58_string = GasfreeSdk::Base58.binary_to_base58(binary_data)The module provides pre-configured domain constants for both networks:
# TRON Testnet (Nile)
GasfreeSdk::TronEIP712Signer::DOMAIN_TESTNET
# => {
# name: "GasFreeController",
# version: "V1.0.0",
# chainId: 728_126_428,
# verifyingContract: "THQGuFzL87ZqhxkgqYEryRAd7gqFqL5rdc"
# }
# TRON Mainnet
GasfreeSdk::TronEIP712Signer::DOMAIN_MAINNET
# => {
# name: "GasFreeController",
# version: "V1.0.0",
# chainId: 3_448_148_188,
# verifyingContract: "TFFAMQLZybALaLb4uxHA9RBE7pxhUAjF3U"
# }# Create and submit a transfer request
token = client.tokens.first
provider = client.providers.first
message_data = {
token: token.token_address,
serviceProvider: provider.address,
user: "TYourTronAddress",
receiver: "TReceiverAddress",
value: "1000000", # 1 USDT
maxFee: "500000", # 0.5 USDT max fee
deadline: (Time.now.to_i + provider.config.default_deadline_duration).to_s,
version: 1,
nonce: account.nonce
}
# Sign the message
signature = GasfreeSdk::TronEIP712Signer.sign_typed_data_testnet(private_key, message_data)
# Create transfer request
request = GasfreeSdk::Models::TransferRequest.new(
token: message_data[:token],
service_provider: message_data[:serviceProvider],
user: message_data[:user],
receiver: message_data[:receiver],
value: message_data[:value],
max_fee: message_data[:maxFee],
deadline: message_data[:deadline].to_i,
version: message_data[:version],
nonce: message_data[:nonce],
sig: signature
)
# Submit the transfer
response = client.submit_transfer(request)
puts "Transfer ID: #{response.id}"
puts "State: #{response.state}"transfer_id = response.id
loop do
status = client.transfer_status(transfer_id)
puts "State: #{status.state}"
puts "Transaction Hash: #{status.txn_hash}" if status.txn_hash
break if %w[SUCCEED FAILED].include?(status.state)
sleep 2
endThe SDK uses a custom Faraday middleware (SanitizedLogsMiddleware) to ensure that all HTTP request and response logs are automatically sanitized. Sensitive data is never written to logs, even in debug mode.
export DEBUG_GASFREE_SDK=1When this environment variable is set, the SDK will log HTTP requests and responses using only sanitized data. This is handled automatically; you do not need to configure anything extra.
- The SDK integrates
SanitizedLogsMiddlewareinto the Faraday stack. - This middleware intercepts all HTTP traffic and logs method, URL, headers, and body with sensitive fields masked (e.g.,
***REDACTED***). - The original data is never mutated, and only masked data is ever written to logs.
- No other HTTP logging middleware is used, so there is no risk of leaking secrets.
client = GasfreeSdk.client
# If DEBUG_GASFREE_SDK=1, all HTTP logs will be sanitized automatically.When debug logging is enabled, sensitive fields (private keys, tokens, signatures, etc.) are automatically masked with ***REDACTED*** in all HTTP request/response logs.
Protected fields include:
- Headers:
Authorization,Api-Key,X-Api-Key, etc. - Body fields:
private_key,api_secret,signature,token, etc.
# With DEBUG_GASFREE_SDK=1
client = GasfreeSdk.client
tokens = client.tokens
# Console output (sensitive data automatically masked):
# GET https://open.gasfree.io/tron/api/v1/config/token/all
# Request Headers: {"Authorization"=>"***REDACTED***", "Timestamp"=>"1703123456"}begin
response = client.submit_transfer(request)
rescue GasfreeSdk::APIError => e
puts "API Error (#{e.code}): #{e.message}"
case e.message
when /insufficient balance/
puts "Solution: Get test tokens or transfer tokens to GasFree address"
when /max fee exceeded/
puts "Solution: Increase maxFee parameter"
when /Invalid signature/
puts "Solution: Check private key and address correspondence"
end
rescue StandardError => e
puts "Error: #{e.message}"
endSee the examples/ directory for complete working examples:
examples/simple_usage_example.rb- Basic TronEIP712Signer usage
dry-configurable- Configuration managementdry-struct- Data structuresdry-types- Type systemdry-validation- Data validationfaraday- HTTP clientfaraday-retry- HTTP retry logiceth- Ethereum utilitiesrbsecp256k1- Cryptographic operations for EIP-712 signatures
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.
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.
Bug reports and pull requests are welcome on GitHub at https://github.com/madmatvey/gasfree_sdk.
The gem is available as open source under the terms of the LGPL v3.0 © 2025 Eugene Leontev (https://github.com/madmatvey)