nowpayments 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.
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NOWPayments
4
+ module API
5
+ # Estimation and calculation endpoints
6
+ module Estimation
7
+ # Get minimum payment amount for currency pair
8
+ # GET /v1/min-amount
9
+ # @param currency_from [String] Source currency code
10
+ # @param currency_to [String] Target currency code
11
+ # @return [Hash] Minimum amount info
12
+ def min_amount(currency_from:, currency_to:)
13
+ get("min-amount", params: {
14
+ currency_from: currency_from,
15
+ currency_to: currency_to
16
+ }).body
17
+ end
18
+
19
+ # Estimate price for currency pair
20
+ # GET /v1/estimate
21
+ # @param amount [Numeric] Amount to estimate
22
+ # @param currency_from [String] Source currency
23
+ # @param currency_to [String] Target currency
24
+ # @return [Hash] Price estimate
25
+ def estimate(amount:, currency_from:, currency_to:)
26
+ get("estimate", params: {
27
+ amount: amount,
28
+ currency_from: currency_from,
29
+ currency_to: currency_to
30
+ }).body
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NOWPayments
4
+ module API
5
+ # Fiat Payouts API endpoints (Beta)
6
+ # All endpoints require JWT authentication
7
+ # Note: This is a Beta feature with limited availability
8
+ module FiatPayouts
9
+ # Get available fiat payment methods
10
+ # GET /v1/fiat-payouts/payment-methods
11
+ # @param fiat_currency [String, nil] Optional filter by fiat currency (e.g., "EUR", "USD")
12
+ # @return [Hash] Available payment methods
13
+ def fiat_payout_payment_methods(fiat_currency: nil)
14
+ params = {}
15
+ params[:fiatCurrency] = fiat_currency if fiat_currency
16
+ get("fiat-payouts/payment-methods", params: params).body
17
+ end
18
+
19
+ # Create a fiat payout account
20
+ # POST /v1/fiat-payouts/account
21
+ # @param provider [String] Payment provider (e.g., "transfi")
22
+ # @param fiat_currency [String] Fiat currency code (e.g., "EUR", "USD")
23
+ # @param account_data [Hash] Provider-specific account data
24
+ # @return [Hash] Created account details
25
+ def create_fiat_payout_account(provider:, fiat_currency:, account_data:)
26
+ params = {
27
+ provider: provider,
28
+ fiatCurrency: fiat_currency,
29
+ accountData: account_data
30
+ }
31
+ post("fiat-payouts/account", body: params).body
32
+ end
33
+
34
+ # Get list of fiat payout accounts
35
+ # GET /v1/fiat-payouts/account
36
+ # @param provider [String, nil] Optional filter by provider
37
+ # @param fiat_currency [String, nil] Optional filter by fiat currency
38
+ # @param limit [Integer] Number of results per page (default: 10)
39
+ # @param page [Integer] Page number (default: 0)
40
+ # @return [Hash] List of payout accounts
41
+ def fiat_payout_accounts(provider: nil, fiat_currency: nil, limit: 10, page: 0)
42
+ params = { limit: limit, page: page }
43
+ params[:provider] = provider if provider
44
+ params[:fiatCurrency] = fiat_currency if fiat_currency
45
+ get("fiat-payouts/account", params: params).body
46
+ end
47
+
48
+ # Update a fiat payout account
49
+ # PATCH /v1/fiat-payouts/account/:account_id
50
+ # @param account_id [String, Integer] Account ID
51
+ # @param account_data [Hash] Updated account data
52
+ # @return [Hash] Updated account details
53
+ def update_fiat_payout_account(account_id:, account_data:)
54
+ params = { accountData: account_data }
55
+ patch("fiat-payouts/account/#{account_id}", body: params).body
56
+ end
57
+
58
+ # Create a fiat payout
59
+ # POST /v1/fiat-payouts
60
+ # @param account_id [String, Integer] Payout account ID
61
+ # @param crypto_currency [String] Cryptocurrency code (e.g., "btc", "eth")
62
+ # @param crypto_amount [Numeric] Amount in cryptocurrency
63
+ # @param request_id [String, nil] Optional unique request ID
64
+ # @return [Hash] Created payout details
65
+ def create_fiat_payout(account_id:, crypto_currency:, crypto_amount:, request_id: nil)
66
+ params = {
67
+ accountId: account_id,
68
+ cryptoCurrency: crypto_currency,
69
+ cryptoAmount: crypto_amount
70
+ }
71
+ params[:requestId] = request_id if request_id
72
+ post("fiat-payouts", body: params).body
73
+ end
74
+
75
+ # Get fiat payout status
76
+ # GET /v1/fiat-payouts/:payout_id
77
+ # @param payout_id [String, Integer] Payout ID
78
+ # @return [Hash] Payout details and status
79
+ def fiat_payout_status(payout_id)
80
+ get("fiat-payouts/#{payout_id}").body
81
+ end
82
+
83
+ # Get list of fiat payouts
84
+ # GET /v1/fiat-payouts
85
+ # @param id [String, Integer, nil] Optional filter by payout ID
86
+ # @param provider [String, nil] Optional filter by provider
87
+ # @param request_id [String, nil] Optional filter by request ID
88
+ # @param fiat_currency [String, nil] Optional filter by fiat currency
89
+ # @param crypto_currency [String, nil] Optional filter by crypto currency
90
+ # @param status [String, nil] Optional filter by status (e.g., "FINISHED", "PENDING")
91
+ # @param filter [String, nil] Optional text filter
92
+ # @param provider_payout_id [String, nil] Optional filter by provider's payout ID
93
+ # @param limit [Integer] Number of results per page (default: 10)
94
+ # @param page [Integer] Page number (default: 0)
95
+ # @param order_by [String, nil] Optional field to order by
96
+ # @param sort_by [String, nil] Optional sort direction ("asc" or "desc")
97
+ # @param date_from [String, nil] Optional start date (ISO 8601)
98
+ # @param date_to [String, nil] Optional end date (ISO 8601)
99
+ # @return [Hash] List of payouts
100
+ def fiat_payouts(
101
+ id: nil,
102
+ provider: nil,
103
+ request_id: nil,
104
+ fiat_currency: nil,
105
+ crypto_currency: nil,
106
+ status: nil,
107
+ filter: nil,
108
+ provider_payout_id: nil,
109
+ limit: 10,
110
+ page: 0,
111
+ order_by: nil,
112
+ sort_by: nil,
113
+ date_from: nil,
114
+ date_to: nil
115
+ )
116
+ params = { limit: limit, page: page }
117
+ params[:id] = id if id
118
+ params[:provider] = provider if provider
119
+ params[:requestId] = request_id if request_id
120
+ params[:fiatCurrency] = fiat_currency if fiat_currency
121
+ params[:cryptoCurrency] = crypto_currency if crypto_currency
122
+ params[:status] = status if status
123
+ params[:filter] = filter if filter
124
+ params[:provider_payout_id] = provider_payout_id if provider_payout_id
125
+ params[:orderBy] = order_by if order_by
126
+ params[:sortBy] = sort_by if sort_by
127
+ params[:dateFrom] = date_from if date_from
128
+ params[:dateTo] = date_to if date_to
129
+ get("fiat-payouts", params: params).body
130
+ end
131
+
132
+ # Get fiat conversion rates
133
+ # POST /v1/fiat-payouts/rates
134
+ # @param crypto_currency [String] Cryptocurrency code (e.g., "btc", "eth")
135
+ # @param fiat_currency [String] Fiat currency code (e.g., "EUR", "USD")
136
+ # @param crypto_amount [Numeric, nil] Optional crypto amount to convert
137
+ # @param fiat_amount [Numeric, nil] Optional fiat amount to convert
138
+ # @return [Hash] Conversion rates and amounts
139
+ def fiat_payout_rates(crypto_currency:, fiat_currency:, crypto_amount: nil, fiat_amount: nil)
140
+ params = {
141
+ cryptoCurrency: crypto_currency,
142
+ fiatCurrency: fiat_currency
143
+ }
144
+ params[:cryptoAmount] = crypto_amount if crypto_amount
145
+ params[:fiatAmount] = fiat_amount if fiat_amount
146
+ post("fiat-payouts/rates", body: params).body
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NOWPayments
4
+ module API
5
+ # Invoice-related endpoints
6
+ module Invoices
7
+ # Create an invoice (hosted payment page)
8
+ # POST /v1/invoice
9
+ # @param price_amount [Numeric] Fiat amount
10
+ # @param price_currency [String] Fiat currency
11
+ # @param pay_currency [String, nil] Optional crypto (if nil, customer chooses)
12
+ # @param order_id [String, nil] Optional merchant order ID
13
+ # @param order_description [String, nil] Optional description
14
+ # @param ipn_callback_url [String, nil] Optional webhook URL
15
+ # @param success_url [String, nil] Optional redirect after success
16
+ # @param cancel_url [String, nil] Optional redirect after cancel
17
+ # @return [Hash] Invoice with invoice_url
18
+ def create_invoice(
19
+ price_amount:,
20
+ price_currency:,
21
+ pay_currency: nil,
22
+ order_id: nil,
23
+ order_description: nil,
24
+ ipn_callback_url: nil,
25
+ success_url: nil,
26
+ cancel_url: nil
27
+ )
28
+ params = {
29
+ price_amount: price_amount,
30
+ price_currency: price_currency
31
+ }
32
+
33
+ params[:pay_currency] = pay_currency if pay_currency
34
+ params[:order_id] = order_id if order_id
35
+ params[:order_description] = order_description if order_description
36
+ params[:ipn_callback_url] = ipn_callback_url if ipn_callback_url
37
+ params[:success_url] = success_url if success_url
38
+ params[:cancel_url] = cancel_url if cancel_url
39
+
40
+ post("invoice", body: params).body
41
+ end
42
+
43
+ # Create payment by invoice
44
+ # POST /v1/invoice-payment
45
+ # @param iid [Integer, String] Invoice ID
46
+ # @param pay_currency [String] Crypto currency
47
+ # @param purchase_id [String, Integer, nil] Optional purchase ID
48
+ # @param order_description [String, nil] Optional description
49
+ # @param customer_email [String, nil] Optional customer email
50
+ # @param payout_address [String, nil] Optional custom payout address
51
+ # @param payout_extra_id [String, nil] Optional extra ID for payout
52
+ # @param payout_currency [String, nil] Required if payout_address set
53
+ # @return [Hash] Payment details
54
+ def create_invoice_payment(
55
+ iid:,
56
+ pay_currency:,
57
+ purchase_id: nil,
58
+ order_description: nil,
59
+ customer_email: nil,
60
+ payout_address: nil,
61
+ payout_extra_id: nil,
62
+ payout_currency: nil
63
+ )
64
+ params = {
65
+ iid: iid,
66
+ pay_currency: pay_currency
67
+ }
68
+
69
+ params[:purchase_id] = purchase_id if purchase_id
70
+ params[:order_description] = order_description if order_description
71
+ params[:customer_email] = customer_email if customer_email
72
+ params[:payout_address] = payout_address if payout_address
73
+ params[:payout_extra_id] = payout_extra_id if payout_extra_id
74
+ params[:payout_currency] = payout_currency if payout_currency
75
+
76
+ post("invoice-payment", body: params).body
77
+ end
78
+
79
+ # Get invoice details and status
80
+ # GET /v1/invoice/:invoice_id
81
+ # @param invoice_id [String, Integer] Invoice ID
82
+ # @return [Hash] Invoice details with payment status
83
+ def invoice(invoice_id)
84
+ get("invoice/#{invoice_id}").body
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NOWPayments
4
+ module API
5
+ # Payment-related endpoints
6
+ module Payments
7
+ # Create a new payment
8
+ # POST /v1/payment
9
+ # @param price_amount [Numeric] Fiat amount
10
+ # @param price_currency [String] Fiat currency
11
+ # @param pay_currency [String] Crypto currency customer pays with
12
+ # @param pay_amount [Numeric, nil] Optional crypto amount (alternative to price_amount)
13
+ # @param order_id [String, nil] Optional merchant order ID
14
+ # @param order_description [String, nil] Optional description
15
+ # @param ipn_callback_url [String, nil] Optional webhook URL
16
+ # @param payout_address [String, nil] Optional custom payout address
17
+ # @param payout_currency [String, nil] Required if payout_address set
18
+ # @param payout_extra_id [String, nil] Optional extra ID for payout
19
+ # @param is_fixed_rate [Boolean, nil] Fixed rate flag
20
+ # @param is_fee_paid_by_user [Boolean, nil] Whether user pays network fees
21
+ # @return [Hash] Payment details
22
+ def create_payment(
23
+ price_amount:,
24
+ price_currency:,
25
+ pay_currency:,
26
+ pay_amount: nil,
27
+ order_id: nil,
28
+ order_description: nil,
29
+ ipn_callback_url: nil,
30
+ payout_address: nil,
31
+ payout_currency: nil,
32
+ payout_extra_id: nil,
33
+ is_fixed_rate: nil,
34
+ is_fee_paid_by_user: nil
35
+ )
36
+ params = {
37
+ price_amount: price_amount,
38
+ price_currency: price_currency,
39
+ pay_currency: pay_currency
40
+ }
41
+
42
+ params[:pay_amount] = pay_amount if pay_amount
43
+ params[:order_id] = order_id if order_id
44
+ params[:order_description] = order_description if order_description
45
+ params[:ipn_callback_url] = ipn_callback_url if ipn_callback_url
46
+ params[:payout_address] = payout_address if payout_address
47
+ params[:payout_currency] = payout_currency if payout_currency
48
+ params[:payout_extra_id] = payout_extra_id if payout_extra_id
49
+ params[:is_fixed_rate] = is_fixed_rate unless is_fixed_rate.nil?
50
+ params[:is_fee_paid_by_user] = is_fee_paid_by_user unless is_fee_paid_by_user.nil?
51
+
52
+ validate_payment_params!(params)
53
+
54
+ post("payment", body: params).body
55
+ end
56
+
57
+ # Get payment status
58
+ # GET /v1/payment/:payment_id
59
+ # @param payment_id [Integer, String] Payment ID
60
+ # @return [Hash] Payment status
61
+ def payment(payment_id)
62
+ get("payment/#{payment_id}").body
63
+ end
64
+
65
+ # List payments with pagination and filters
66
+ # GET /v1/payment
67
+ # @param limit [Integer] Results per page
68
+ # @param page [Integer] Page number
69
+ # @param sort_by [String, nil] Sort field
70
+ # @param order_by [String, nil] Order direction (asc/desc)
71
+ # @param date_from [String, nil] Start date filter
72
+ # @param date_to [String, nil] End date filter
73
+ # @return [Hash] List of payments
74
+ def payments(limit: 10, page: 0, sort_by: nil, order_by: nil, date_from: nil, date_to: nil)
75
+ params = { limit: limit, page: page }
76
+ params[:sortBy] = sort_by if sort_by
77
+ params[:orderBy] = order_by if order_by
78
+ params[:dateFrom] = date_from if date_from
79
+ params[:dateTo] = date_to if date_to
80
+
81
+ get("payment", params: params).body
82
+ end
83
+
84
+ # Update payment estimate
85
+ # PATCH /v1/payment/:payment_id
86
+ # @param payment_id [Integer, String] Payment ID
87
+ # @return [Hash] Updated payment
88
+ def update_payment_estimate(payment_id)
89
+ patch("payment/#{payment_id}").body
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NOWPayments
4
+ module API
5
+ # Payout and mass payout endpoints (requires JWT auth)
6
+ module Payouts
7
+ # Get account balance
8
+ # GET /v1/balance
9
+ # @return [Hash] Balance information with available and pending amounts per currency
10
+ def balance
11
+ get("balance").body
12
+ end
13
+
14
+ # Validate payout address
15
+ # POST /v1/payout/validate-address
16
+ # @param address [String] Payout address to validate
17
+ # @param currency [String] Currency code
18
+ # @param extra_id [String, nil] Optional memo/tag/destination tag
19
+ # @return [Hash] Validation result
20
+ def validate_payout_address(address:, currency:, extra_id: nil)
21
+ params = {
22
+ address: address,
23
+ currency: currency
24
+ }
25
+ params[:extra_id] = extra_id if extra_id
26
+
27
+ post("payout/validate-address", body: params).body
28
+ end
29
+
30
+ # Create payout
31
+ # POST /v1/payout
32
+ # Note: This endpoint requires JWT authentication
33
+ # @param withdrawals [Array<Hash>] Array of withdrawal objects
34
+ # Each withdrawal should have:
35
+ # - address (String, required): Crypto address
36
+ # - currency (String, required): Currency code
37
+ # - amount (Numeric, required): Amount to send
38
+ # - ipn_callback_url (String, optional): Individual callback URL
39
+ # - extra_id (String, optional): Payment extra ID (memo/tag)
40
+ # - fiat_amount (Numeric, optional): Fiat equivalent amount
41
+ # - fiat_currency (String, optional): Fiat currency code
42
+ # - unique_external_id (String, optional): External reference ID
43
+ # - payout_description (String, optional): Individual description
44
+ # @param payout_description [String, nil] Description for entire batch
45
+ # @param ipn_callback_url [String, nil] Callback URL for entire batch
46
+ # @return [Hash] Payout result
47
+ def create_payout(withdrawals:, payout_description: nil, ipn_callback_url: nil)
48
+ params = { withdrawals: withdrawals }
49
+ params[:payout_description] = payout_description if payout_description
50
+ params[:ipn_callback_url] = ipn_callback_url if ipn_callback_url
51
+
52
+ post("payout", body: params).body
53
+ end
54
+
55
+ # Verify payout with 2FA code
56
+ # POST /v1/payout/:batch_withdrawal_id/verify
57
+ # @param batch_withdrawal_id [String, Integer] Batch withdrawal ID from create_payout
58
+ # @param verification_code [String] 2FA code from Google Auth app or email
59
+ # @return [Hash] Verification result
60
+ def verify_payout(batch_withdrawal_id:, verification_code:)
61
+ post("payout/#{batch_withdrawal_id}/verify", body: {
62
+ verification_code: verification_code
63
+ }).body
64
+ end
65
+
66
+ # Get payout status
67
+ # GET /v1/payout/:payout_id
68
+ # @param payout_id [String, Integer] Payout ID
69
+ # @return [Hash] Payout status and details
70
+ def payout_status(payout_id)
71
+ get("payout/#{payout_id}").body
72
+ end
73
+
74
+ # List payouts with pagination
75
+ # GET /v1/payout
76
+ # @param limit [Integer] Results per page
77
+ # @param offset [Integer] Offset for pagination
78
+ # @return [Hash] List of payouts
79
+ def list_payouts(limit: 10, offset: 0)
80
+ get("payout", params: {
81
+ limit: limit,
82
+ offset: offset
83
+ }).body
84
+ end
85
+
86
+ # Get minimum payout amount
87
+ # GET /v1/payout/min-amount
88
+ # @param currency [String] Currency code
89
+ # @return [Hash] Minimum payout amount for currency
90
+ def min_payout_amount(currency:)
91
+ get("payout/min-amount", params: { currency: currency }).body
92
+ end
93
+
94
+ # Get payout fee estimate
95
+ # GET /v1/payout/fee
96
+ # @param currency [String] Currency code
97
+ # @param amount [Numeric] Payout amount
98
+ # @return [Hash] Fee estimate
99
+ def payout_fee(currency:, amount:)
100
+ get("payout/fee", params: {
101
+ currency: currency,
102
+ amount: amount
103
+ }).body
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NOWPayments
4
+ module API
5
+ # Status and utility endpoints
6
+ module Status
7
+ # Check API status
8
+ # GET /v1/status
9
+ # @return [Hash] Status response
10
+ def status
11
+ get("status").body
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NOWPayments
4
+ module API
5
+ # Subscription and recurring payment endpoints
6
+ module Subscriptions
7
+ # Get subscription plans
8
+ # GET /v1/subscriptions/plans
9
+ # @return [Hash] List of subscription plans
10
+ def subscription_plans
11
+ get("subscriptions/plans").body
12
+ end
13
+
14
+ # Create subscription plan
15
+ # POST /v1/subscriptions/plans
16
+ # @param plan_data [Hash] Plan configuration
17
+ # @return [Hash] Created plan
18
+ def create_subscription_plan(plan_data)
19
+ post("subscriptions/plans", body: plan_data).body
20
+ end
21
+
22
+ # Update subscription plan
23
+ # PATCH /v1/subscriptions/plans/:plan_id
24
+ # @param plan_id [String, Integer] Plan ID
25
+ # @param plan_data [Hash] Updated plan configuration
26
+ # @return [Hash] Updated plan details
27
+ def update_subscription_plan(plan_id, plan_data)
28
+ patch("subscriptions/plans/#{plan_id}", body: plan_data).body
29
+ end
30
+
31
+ # Get specific subscription plan
32
+ # GET /v1/subscriptions/plans/:plan_id
33
+ # @param plan_id [String, Integer] Plan ID
34
+ # @return [Hash] Plan details
35
+ def subscription_plan(plan_id)
36
+ get("subscriptions/plans/#{plan_id}").body
37
+ end
38
+
39
+ # Create email subscription
40
+ # POST /v1/subscriptions
41
+ # @param plan_id [String] Subscription plan ID
42
+ # @param email [String] Customer email
43
+ # @return [Hash] Subscription result
44
+ def create_subscription(plan_id:, email:)
45
+ post("subscriptions", body: {
46
+ plan_id: plan_id,
47
+ email: email
48
+ }).body
49
+ end
50
+
51
+ # List recurring payments with filters
52
+ # GET /v1/subscriptions
53
+ # @param limit [Integer] Results per page
54
+ # @param offset [Integer] Offset for pagination
55
+ # @param status [String, nil] Filter by status (WAITING_PAY, PAID, PARTIALLY_PAID, EXPIRED)
56
+ # @param subscription_plan_id [String, Integer, nil] Filter by plan ID
57
+ # @param is_active [Boolean, nil] Filter by active status
58
+ # @return [Hash] List of recurring payments
59
+ def list_recurring_payments(limit: 10, offset: 0, status: nil, subscription_plan_id: nil, is_active: nil)
60
+ params = { limit: limit, offset: offset }
61
+ params[:status] = status if status
62
+ params[:subscription_plan_id] = subscription_plan_id if subscription_plan_id
63
+ params[:is_active] = is_active unless is_active.nil?
64
+
65
+ get("subscriptions", params: params).body
66
+ end
67
+
68
+ # Get specific recurring payment
69
+ # GET /v1/subscriptions/:subscription_id
70
+ # @param subscription_id [String, Integer] Subscription ID
71
+ # @return [Hash] Recurring payment details
72
+ def recurring_payment(subscription_id)
73
+ get("subscriptions/#{subscription_id}").body
74
+ end
75
+
76
+ # Delete recurring payment
77
+ # DELETE /v1/subscriptions/:subscription_id
78
+ # @param subscription_id [String, Integer] Subscription ID
79
+ # @return [Hash] Deletion result
80
+ def delete_recurring_payment(subscription_id)
81
+ delete("subscriptions/#{subscription_id}").body
82
+ end
83
+
84
+ # Get subscription payments
85
+ # GET /v1/subscriptions/:subscription_id/payments
86
+ # @param subscription_id [String, Integer] Subscription ID
87
+ # @return [Hash] Subscription payments
88
+ def subscription_payments(subscription_id)
89
+ get("subscriptions/#{subscription_id}/payments").body
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday"
4
+ require "json"
5
+ require_relative "api/status"
6
+ require_relative "api/authentication"
7
+ require_relative "api/currencies"
8
+ require_relative "api/estimation"
9
+ require_relative "api/payments"
10
+ require_relative "api/invoices"
11
+ require_relative "api/payouts"
12
+ require_relative "api/subscriptions"
13
+ require_relative "api/conversions"
14
+ require_relative "api/custody"
15
+ require_relative "api/fiat_payouts"
16
+
17
+ module NOWPayments
18
+ # Main client for interacting with the NOWPayments API
19
+ class Client
20
+ include API::Status
21
+ include API::Authentication
22
+ include API::Currencies
23
+ include API::Estimation
24
+ include API::Payments
25
+ include API::Invoices
26
+ include API::Payouts
27
+ include API::Subscriptions
28
+ include API::Conversions
29
+ include API::Custody
30
+ include API::FiatPayouts
31
+
32
+ attr_reader :api_key, :ipn_secret, :sandbox
33
+ attr_accessor :jwt_token, :jwt_expires_at
34
+
35
+ BASE_URL = "https://api.nowpayments.io/v1"
36
+ SANDBOX_URL = "https://api-sandbox.nowpayments.io/v1"
37
+
38
+ def initialize(api_key:, ipn_secret: nil, sandbox: false)
39
+ @api_key = api_key
40
+ @ipn_secret = ipn_secret
41
+ @sandbox = sandbox
42
+ @jwt_token = nil
43
+ @jwt_expires_at = nil
44
+ end
45
+
46
+ def base_url
47
+ sandbox ? SANDBOX_URL : BASE_URL
48
+ end
49
+
50
+ private
51
+
52
+ def connection
53
+ @connection ||= Faraday.new(url: base_url) do |faraday|
54
+ faraday.request :json
55
+ faraday.response :json, content_type: /\bjson$/
56
+ faraday.adapter Faraday.default_adapter
57
+ faraday.headers["x-api-key"] = @api_key
58
+
59
+ # Add JWT Bearer token if available and not expired
60
+ faraday.headers["Authorization"] = "Bearer #{@jwt_token}" if @jwt_token && !jwt_expired?
61
+ end
62
+ end
63
+
64
+ # Reset connection when JWT token changes
65
+ def reset_connection!
66
+ @connection = nil
67
+ end
68
+
69
+ def get(path, params: {})
70
+ connection.get(path, params)
71
+ end
72
+
73
+ def post(path, body: {})
74
+ connection.post(path, body.to_json)
75
+ end
76
+
77
+ def patch(path, body: {})
78
+ connection.patch(path, body.to_json)
79
+ end
80
+
81
+ def delete(path, params: {})
82
+ connection.delete(path, params)
83
+ end
84
+
85
+ def validate_payment_params!(params)
86
+ return unless params[:payout_address] && !params[:payout_currency]
87
+
88
+ raise ValidationError, "payout_currency required when payout_address is set"
89
+ end
90
+ end
91
+ end