weft-sdk 0.25.0 → 0.32.2
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 +4 -4
- data/docs/FetchApi.md +3 -3
- data/docs/FetchErrorResponse.md +1 -1
- data/docs/FetchRequest.md +6 -2
- data/docs/FetchResponse.md +5 -3
- data/docs/GetPurchaseIdParameter.md +48 -0
- data/docs/PaymentsApi.md +2 -0
- data/docs/Purchase.md +6 -0
- data/docs/PurchasesApi.md +2 -2
- data/docs/SearchApi.md +1 -1
- data/docs/SearchCompactAccess.md +23 -0
- data/docs/SearchCompactAccessPrice.md +23 -0
- data/docs/SearchCompactNextCall.md +23 -0
- data/docs/SearchCompactResult.md +47 -0
- data/docs/SearchCompactResultAttribution.md +21 -0
- data/docs/SearchCompactResultBlockedScopesInner.md +19 -0
- data/docs/SearchCompactResultOperation.md +21 -0
- data/docs/SearchCompactResultProvider.md +19 -0
- data/docs/SearchEndpointCall.md +1 -1
- data/docs/SearchEndpointCallInputSchema.md +14 -0
- data/docs/SearchEndpointHit.md +5 -1
- data/docs/SearchHelperDocs.md +23 -0
- data/docs/SearchRequest.md +3 -1
- data/docs/SearchResponse.md +9 -3
- data/docs/SearchWeftFetchCompatibility.md +3 -1
- data/docs/WebhooksApi.md +414 -0
- data/lib/weft/client.rb +271 -0
- data/lib/weft/error.rb +41 -0
- data/lib/weft/facilitator/client.rb +179 -42
- data/lib/weft/facilitator/echo.rb +99 -0
- data/lib/weft/facilitator/extensions.rb +183 -0
- data/lib/weft/facilitator/fee.rb +26 -11
- data/lib/weft/facilitator/handshake.rb +92 -0
- data/lib/weft/facilitator/json_wire.rb +74 -0
- data/lib/weft/facilitator/middleware.rb +562 -137
- data/lib/weft/facilitator/path_match.rb +179 -0
- data/lib/weft/facilitator/product.rb +380 -0
- data/lib/weft/facilitator/replay.rb +46 -0
- data/lib/weft/facilitator/settlement.rb +117 -0
- data/lib/weft/facilitator/x402.rb +355 -0
- data/lib/weft/generated/api/account_api.rb +2 -2
- data/lib/weft/generated/api/agent_bootstrap_api.rb +2 -2
- data/lib/weft/generated/api/api_keys_api.rb +2 -2
- data/lib/weft/generated/api/auth_api.rb +2 -2
- data/lib/weft/generated/api/balance_api.rb +2 -2
- data/lib/weft/generated/api/documentation_api.rb +2 -2
- data/lib/weft/generated/api/fetch_api.rb +6 -6
- data/lib/weft/generated/api/payments_api.rb +4 -2
- data/lib/weft/generated/api/purchases_api.rb +4 -4
- data/lib/weft/generated/api/resources_api.rb +2 -2
- data/lib/weft/generated/api/search_api.rb +4 -4
- data/lib/weft/generated/api/webhooks_api.rb +388 -0
- data/lib/weft/generated/api_client.rb +2 -2
- data/lib/weft/generated/api_error.rb +2 -2
- data/lib/weft/generated/api_model_base.rb +2 -2
- data/lib/weft/generated/configuration.rb +2 -2
- data/lib/weft/generated/models/account_bootstrap_approval.rb +2 -2
- data/lib/weft/generated/models/account_bootstrap_created.rb +2 -2
- data/lib/weft/generated/models/account_bootstrap_created_approval.rb +2 -2
- data/lib/weft/generated/models/account_bootstrap_created_response.rb +2 -2
- data/lib/weft/generated/models/account_bootstrap_request.rb +2 -2
- data/lib/weft/generated/models/account_bootstrap_status.rb +2 -2
- data/lib/weft/generated/models/account_bootstrap_status_response.rb +2 -2
- data/lib/weft/generated/models/account_details.rb +2 -2
- data/lib/weft/generated/models/api_key.rb +2 -2
- data/lib/weft/generated/models/api_key_created.rb +2 -2
- data/lib/weft/generated/models/api_key_created_response.rb +2 -2
- data/lib/weft/generated/models/api_key_list_response.rb +2 -2
- data/lib/weft/generated/models/auth_response.rb +2 -2
- data/lib/weft/generated/models/auth_response_data.rb +2 -2
- data/lib/weft/generated/models/balance_response.rb +2 -2
- data/lib/weft/generated/models/confirm_request.rb +2 -2
- data/lib/weft/generated/models/create_api_key_request.rb +2 -2
- data/lib/weft/generated/models/enrolled_resource.rb +2 -2
- data/lib/weft/generated/models/error.rb +2 -2
- data/lib/weft/generated/models/error_response.rb +2 -2
- data/lib/weft/generated/models/fetch403_response.rb +2 -2
- data/lib/weft/generated/models/fetch_balance_snapshot.rb +2 -2
- data/lib/weft/generated/models/fetch_error_response.rb +5 -5
- data/lib/weft/generated/models/fetch_request.rb +46 -5
- data/lib/weft/generated/models/fetch_request_body.rb +2 -2
- data/lib/weft/generated/models/fetch_response.rb +36 -64
- data/lib/weft/generated/models/get_purchase_id_parameter.rb +104 -0
- data/lib/weft/generated/models/insufficient_scope_response.rb +2 -2
- data/lib/weft/generated/models/me_api_key.rb +2 -2
- data/lib/weft/generated/models/me_api_key_creator.rb +2 -2
- data/lib/weft/generated/models/me_response.rb +2 -2
- data/lib/weft/generated/models/me_response_data.rb +2 -2
- data/lib/weft/generated/models/message_response.rb +2 -2
- data/lib/weft/generated/models/message_response_data.rb +2 -2
- data/lib/weft/generated/models/pagination.rb +2 -2
- data/lib/weft/generated/models/password_reset_request.rb +2 -2
- data/lib/weft/generated/models/password_update_request.rb +2 -2
- data/lib/weft/generated/models/payment.rb +2 -2
- data/lib/weft/generated/models/payment_list_response.rb +2 -2
- data/lib/weft/generated/models/payment_response.rb +2 -2
- data/lib/weft/generated/models/principal_wallet.rb +2 -2
- data/lib/weft/generated/models/promo_balance.rb +2 -2
- data/lib/weft/generated/models/purchase.rb +75 -3
- data/lib/weft/generated/models/purchase_artifact.rb +2 -2
- data/lib/weft/generated/models/purchase_list_response.rb +2 -2
- data/lib/weft/generated/models/purchase_response.rb +2 -2
- data/lib/weft/generated/models/rate_limit_response.rb +2 -2
- data/lib/weft/generated/models/resend_confirmation_request.rb +2 -2
- data/lib/weft/generated/models/resource_enrollment_request.rb +2 -2
- data/lib/weft/generated/models/resource_enrollment_response.rb +2 -2
- data/lib/weft/generated/models/resource_stats.rb +2 -2
- data/lib/weft/generated/models/search_access_method.rb +2 -2
- data/lib/weft/generated/models/search_capability_ref.rb +2 -2
- data/lib/weft/generated/models/search_compact_access.rb +179 -0
- data/lib/weft/generated/models/search_compact_access_price.rb +176 -0
- data/lib/weft/generated/models/search_compact_next_call.rb +275 -0
- data/lib/weft/generated/models/search_compact_result.rb +389 -0
- data/lib/weft/generated/models/search_compact_result_attribution.rb +166 -0
- data/lib/weft/generated/models/search_compact_result_blocked_scopes_inner.rb +156 -0
- data/lib/weft/generated/models/search_compact_result_operation.rb +183 -0
- data/lib/weft/generated/models/search_compact_result_provider.rb +156 -0
- data/lib/weft/generated/models/search_curated_callability.rb +2 -2
- data/lib/weft/generated/models/search_curated_execution.rb +2 -2
- data/lib/weft/generated/models/search_curated_operation.rb +2 -2
- data/lib/weft/generated/models/search_curated_service.rb +2 -2
- data/lib/weft/generated/models/search_curated_source.rb +2 -2
- data/lib/weft/generated/models/search_endpoint_call.rb +4 -4
- data/lib/weft/generated/models/search_endpoint_call_input_schema.rb +103 -0
- data/lib/weft/generated/models/search_endpoint_hit.rb +25 -6
- data/lib/weft/generated/models/search_endpoint_price.rb +2 -2
- data/lib/weft/generated/models/search_error_response.rb +4 -4
- data/lib/weft/generated/models/search_execution_mode_filter.rb +2 -2
- data/lib/weft/generated/models/search_filter_spec.rb +2 -2
- data/lib/weft/generated/models/search_helper_docs.rb +175 -0
- data/lib/weft/generated/models/search_method_filter.rb +2 -2
- data/lib/weft/generated/models/search_payment_offer.rb +2 -2
- data/lib/weft/generated/models/search_price_atomic_filter.rb +2 -2
- data/lib/weft/generated/models/search_price_usd_filter.rb +2 -2
- data/lib/weft/generated/models/search_protocol_filter.rb +2 -2
- data/lib/weft/generated/models/search_provider_ref.rb +2 -2
- data/lib/weft/generated/models/search_request.rb +50 -6
- data/lib/weft/generated/models/search_resource_type_filter.rb +2 -2
- data/lib/weft/generated/models/search_response.rb +71 -8
- data/lib/weft/generated/models/search_response_warnings_inner.rb +2 -2
- data/lib/weft/generated/models/search_result.rb +2 -2
- data/lib/weft/generated/models/search_string_set_filter.rb +2 -2
- data/lib/weft/generated/models/search_weft_fetch_compatibility.rb +28 -6
- data/lib/weft/generated/models/sign_in_request.rb +2 -2
- data/lib/weft/generated/models/sign_up_request.rb +2 -2
- data/lib/weft/generated/models/spending_policy.rb +2 -2
- data/lib/weft/generated/models/user.rb +2 -2
- data/lib/weft/generated/models/user_principal.rb +2 -2
- data/lib/weft/generated/models/wallet.rb +2 -2
- data/lib/weft/generated/version.rb +3 -3
- data/lib/weft/sdk.rb +3 -1
- metadata +39 -4
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
require_relative 'json_wire'
|
|
6
|
+
|
|
7
|
+
module Weft
|
|
8
|
+
module Facilitator
|
|
9
|
+
FACILITATOR_UNAVAILABLE_ERROR = 'weft:facilitator-settle-unavailable'
|
|
10
|
+
CORE_FACILITATOR_UNAVAILABLE = /^Facilitator settle failed \(503\):(?: |$)/
|
|
11
|
+
SETTLEMENT_OVERRIDES_HEADER = 'Settlement-Overrides'
|
|
12
|
+
PAYMENT_REQUIRED_CACHE_CONTROL = 'no-store'
|
|
13
|
+
SYNC_RETRY_FLOOR_MS = 30_000
|
|
14
|
+
|
|
15
|
+
module Settlement
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
def facilitator_unavailable?(reason)
|
|
19
|
+
return false if reason.nil?
|
|
20
|
+
|
|
21
|
+
text = reason.to_s
|
|
22
|
+
text == FACILITATOR_UNAVAILABLE_ERROR || CORE_FACILITATOR_UNAVAILABLE.match?(text)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def with_private_cache_control(value)
|
|
26
|
+
return 'private' if value.nil? || value.to_s.empty?
|
|
27
|
+
|
|
28
|
+
directives = value.to_s.split(',').map { |part| part.strip.downcase }
|
|
29
|
+
return value if directives.include?('private')
|
|
30
|
+
|
|
31
|
+
"#{value}, private"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def json_response?(headers)
|
|
35
|
+
content_type = header_value(headers, 'content-type')
|
|
36
|
+
return false if content_type.nil?
|
|
37
|
+
|
|
38
|
+
/^(application\/json|[^;]+\+json)(?:;|$)/i.match?(content_type)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def header_value(headers, name)
|
|
42
|
+
return nil unless headers.is_a?(Hash)
|
|
43
|
+
|
|
44
|
+
pair = headers.find { |key, _| key.to_s.casecmp?(name) }
|
|
45
|
+
return nil unless pair
|
|
46
|
+
|
|
47
|
+
value = pair[1]
|
|
48
|
+
value.is_a?(Array) ? value[0] : value
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def unavailable_response?(response)
|
|
52
|
+
body = response[:body] || response['body']
|
|
53
|
+
if body.is_a?(Hash)
|
|
54
|
+
%w[errorReason error].each do |field|
|
|
55
|
+
text = body[field] || body[field.to_sym]
|
|
56
|
+
return true if text.is_a?(String) && facilitator_unavailable?(text)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
encoded = header_value(response[:headers] || response['headers'], 'payment-response')
|
|
61
|
+
return false if encoded.nil? || encoded.empty?
|
|
62
|
+
|
|
63
|
+
decoded = JSON.parse(JsonWire.base64_decode(encoded))
|
|
64
|
+
facilitator_unavailable?(decoded['errorReason'])
|
|
65
|
+
rescue StandardError
|
|
66
|
+
false
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class SettleError < StandardError
|
|
71
|
+
attr_reader :status_code, :error_reason, :error_message, :payer, :transaction, :network
|
|
72
|
+
|
|
73
|
+
def initialize(status_code, response)
|
|
74
|
+
response = {} unless response.is_a?(Hash)
|
|
75
|
+
@status_code = status_code
|
|
76
|
+
@error_reason = response['errorReason'] || response[:errorReason]
|
|
77
|
+
@error_message = response['errorMessage'] || response[:errorMessage]
|
|
78
|
+
@payer = response['payer'] || response[:payer]
|
|
79
|
+
@transaction = response['transaction'] || response[:transaction]
|
|
80
|
+
@network = response['network'] || response[:network]
|
|
81
|
+
reason = @error_reason || 'unknown reason'
|
|
82
|
+
message = @error_message
|
|
83
|
+
super(message ? "#{reason}: #{message}" : reason.to_s)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class FacilitatorUnavailableError < StandardError
|
|
88
|
+
def initialize
|
|
89
|
+
super(FACILITATOR_UNAVAILABLE_ERROR)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def status_code
|
|
93
|
+
503
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
module SettleErrors
|
|
98
|
+
module_function
|
|
99
|
+
|
|
100
|
+
def unavailable?(error)
|
|
101
|
+
return false unless error.is_a?(SettleError)
|
|
102
|
+
return false unless error.status_code == 503
|
|
103
|
+
return false unless defined_field?(error, :@error_reason)
|
|
104
|
+
return false unless defined_field?(error, :@error_message)
|
|
105
|
+
return false unless defined_field?(error, :@payer)
|
|
106
|
+
return false unless defined_field?(error, :@transaction)
|
|
107
|
+
return false unless defined_field?(error, :@network)
|
|
108
|
+
|
|
109
|
+
!(error.error_reason == 'settlement_pending' && !error.transaction.to_s.empty?)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def defined_field?(error, name)
|
|
113
|
+
error.instance_variable_defined?(name)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
require 'uri'
|
|
5
|
+
|
|
6
|
+
require_relative 'extensions'
|
|
7
|
+
require_relative 'path_match'
|
|
8
|
+
require_relative 'json_wire'
|
|
9
|
+
require_relative 'settlement'
|
|
10
|
+
|
|
11
|
+
module Weft
|
|
12
|
+
module Facilitator
|
|
13
|
+
PAYMENT_FLOWS = {
|
|
14
|
+
'authorization' => {
|
|
15
|
+
'verifyBeforeHandler' => true,
|
|
16
|
+
'settleBeforeHandler' => false,
|
|
17
|
+
'settleAfterHandler' => true
|
|
18
|
+
},
|
|
19
|
+
'upfront' => {
|
|
20
|
+
'verifyBeforeHandler' => false,
|
|
21
|
+
'settleBeforeHandler' => true,
|
|
22
|
+
'settleAfterHandler' => false
|
|
23
|
+
},
|
|
24
|
+
'escrow' => {
|
|
25
|
+
'verifyBeforeHandler' => false,
|
|
26
|
+
'settleBeforeHandler' => true,
|
|
27
|
+
'settleAfterHandler' => true
|
|
28
|
+
}
|
|
29
|
+
}.freeze
|
|
30
|
+
|
|
31
|
+
FALLBACK_PAYWALL_HTML = <<~HTML.freeze
|
|
32
|
+
<!DOCTYPE html>
|
|
33
|
+
<html>
|
|
34
|
+
<head>
|
|
35
|
+
<title>Payment Required</title>
|
|
36
|
+
<meta charset="UTF-8">
|
|
37
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
38
|
+
</head>
|
|
39
|
+
<body>
|
|
40
|
+
<div style="max-width: 600px; margin: 50px auto; padding: 20px; font-family: system-ui, -apple-system, sans-serif;">
|
|
41
|
+
<h1>Payment Required</h1>
|
|
42
|
+
<p>This resource is protected by the x402 payment protocol.</p>
|
|
43
|
+
<p style="margin-top: 2rem; padding: 1rem; background: #fef3c7; border-radius: 0.5rem;">
|
|
44
|
+
<strong>Note to developers:</strong> install <code>@x402/paywall</code> to enable
|
|
45
|
+
the in-browser wallet connection and payment UI. Programmatic clients should read
|
|
46
|
+
the payment requirements from the 402 response headers and JSON body.
|
|
47
|
+
</p>
|
|
48
|
+
</div>
|
|
49
|
+
</body>
|
|
50
|
+
</html>
|
|
51
|
+
HTML
|
|
52
|
+
|
|
53
|
+
module X402
|
|
54
|
+
module_function
|
|
55
|
+
|
|
56
|
+
def encode_payment_required(value)
|
|
57
|
+
JsonWire.encode_json(value)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def encode_payment_response(value)
|
|
61
|
+
JsonWire.encode_json(value)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def decode_payment_signature(header)
|
|
65
|
+
JSON.parse(JsonWire.base64_decode(header))
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def parse_route_pattern(pattern)
|
|
69
|
+
verb, path = PathMatch.split_verb(pattern)
|
|
70
|
+
{
|
|
71
|
+
'verb' => verb.upcase,
|
|
72
|
+
'regex' => PathMatch.compile_route(path),
|
|
73
|
+
'path' => path
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def route_matches?(pattern, method, path)
|
|
78
|
+
parsed = parse_route_pattern(pattern)
|
|
79
|
+
normalized = normalize_path(path)
|
|
80
|
+
upper = method.to_s.upcase
|
|
81
|
+
return false unless parsed['verb'] == '*' || parsed['verb'] == upper
|
|
82
|
+
|
|
83
|
+
parsed['regex'].match?(normalized)
|
|
84
|
+
rescue Regexp::TimeoutError
|
|
85
|
+
true
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def network_matches?(pattern, network)
|
|
89
|
+
PathMatch.glob_match?(pattern, network)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def normalize_path(path)
|
|
93
|
+
text = path.to_s
|
|
94
|
+
question = text.index('?')
|
|
95
|
+
hash = text.index('#')
|
|
96
|
+
cut = [question, hash].compact.min
|
|
97
|
+
text = text[0, cut] if cut
|
|
98
|
+
normalized = text.split('/', -1).map do |segment|
|
|
99
|
+
decoded = decode_component(segment)
|
|
100
|
+
decoded.gsub('/', '%2F').gsub('\\', '%5C')
|
|
101
|
+
end.join('/')
|
|
102
|
+
PathMatch.trim_trailing_slashes_keep_root(PathMatch.collapse_slashes(normalized))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def decode_component(segment)
|
|
106
|
+
decoded = segment.gsub(/%([0-9A-Fa-f]{2})/) do
|
|
107
|
+
[Regexp.last_match(1)].pack('H*').force_encoding(Encoding::UTF_8)
|
|
108
|
+
end
|
|
109
|
+
decoded.valid_encoding? ? decoded : segment
|
|
110
|
+
rescue StandardError
|
|
111
|
+
segment
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def resolve_payment_flow(scheme, requirements)
|
|
115
|
+
extra = Product.read(requirements, 'extra')
|
|
116
|
+
atm = extra.is_a?(Hash) && (extra['assetTransferMethod'] || extra[:assetTransferMethod]).is_a?(String) ?
|
|
117
|
+
(extra['assetTransferMethod'] || extra[:assetTransferMethod]) :
|
|
118
|
+
(Product.read(scheme, 'defaultAssetTransferMethod') || 'authorization')
|
|
119
|
+
flows = Product.read(scheme, 'paymentFlows') || {}
|
|
120
|
+
config = flows[atm] || flows[atm.to_sym]
|
|
121
|
+
unless config.is_a?(Hash)
|
|
122
|
+
raise ArgumentError,
|
|
123
|
+
"[x402] Scheme \"#{Product.read(scheme, 'scheme')}\" does not support assetTransferMethod \"#{atm}\"."
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
supported = Product.read(config, 'supported') || []
|
|
127
|
+
default_flow = Product.read(config, 'default')
|
|
128
|
+
requested = extra.is_a?(Hash) ? (extra['paymentFlow'] || extra[:paymentFlow]) : nil
|
|
129
|
+
flow = requested.nil? ? default_flow : requested
|
|
130
|
+
unless supported.include?(flow)
|
|
131
|
+
raise ArgumentError, "[x402] Unsupported paymentFlow \"#{flow}\"."
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
{ 'assetTransferMethod' => atm, 'paymentFlow' => flow }
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def apply_payment_flow_wire_extra(extra, resolved)
|
|
138
|
+
next_extra = Product.stringify_hash(extra || {})
|
|
139
|
+
if resolved['assetTransferMethod'] == 'default' || next_extra['assetTransferMethod'] == 'default'
|
|
140
|
+
next_extra.delete('assetTransferMethod')
|
|
141
|
+
end
|
|
142
|
+
next_extra['paymentFlow'] = resolved['paymentFlow'] unless resolved['paymentFlow'] == 'authorization'
|
|
143
|
+
next_extra
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def payment_flow_phases(flow)
|
|
147
|
+
phases = PAYMENT_FLOWS[flow.to_s]
|
|
148
|
+
raise ArgumentError, "[x402] Unknown payment flow \"#{flow}\"." unless phases
|
|
149
|
+
|
|
150
|
+
phases
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def convert_to_token_amount(decimal_amount, decimals)
|
|
154
|
+
if decimal_amount.include?('e') || decimal_amount.include?('E')
|
|
155
|
+
raise ArgumentError, "Invalid amount: #{decimal_amount}"
|
|
156
|
+
end
|
|
157
|
+
unless PathMatch.decimal_amount?(decimal_amount)
|
|
158
|
+
raise ArgumentError, "Invalid amount: #{decimal_amount}"
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
int_part, dec_part = decimal_amount.split('.', 2)
|
|
162
|
+
padded = (dec_part || '').ljust(decimals, '0')[0, decimals]
|
|
163
|
+
PathMatch.strip_leading_zeros(int_part + padded)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def resolve_settlement_override_amount(raw_amount, requirements, decimals)
|
|
167
|
+
if (match = raw_amount.match(/\A(\d+(?:\.\d{0,2})?)%\z/))
|
|
168
|
+
int_part, dec_part = match[1].split('.', 2)
|
|
169
|
+
scaled = (int_part.to_i * 100) + dec_part.to_s.ljust(2, '0')[0, 2].to_i
|
|
170
|
+
base = requirements['amount'].to_i
|
|
171
|
+
return ((base * scaled) / 10_000).to_s
|
|
172
|
+
end
|
|
173
|
+
if (match = raw_amount.match(/\A\$(\d+(?:\.\d+)?)\z/))
|
|
174
|
+
if decimals.nil?
|
|
175
|
+
raise ArgumentError,
|
|
176
|
+
"Cannot convert dollar settlement override \"#{raw_amount}\" to atomic units: " \
|
|
177
|
+
'asset decimals are unknown. Pass an atomic amount or register the asset.'
|
|
178
|
+
end
|
|
179
|
+
return convert_to_token_amount(match[1], decimals)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
raw_amount
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
class ResourceServer
|
|
187
|
+
def initialize(client)
|
|
188
|
+
@client = client
|
|
189
|
+
@schemes = {}
|
|
190
|
+
@kinds = []
|
|
191
|
+
@extensions = {}
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
attr_reader :client
|
|
195
|
+
|
|
196
|
+
def register(network, scheme)
|
|
197
|
+
@schemes[network] ||= {}
|
|
198
|
+
@schemes[network][Product.read(scheme, 'scheme')] = scheme
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def register_extension(extension)
|
|
202
|
+
key = extension.respond_to?(:key) ? extension.key : extension[:key]
|
|
203
|
+
@extensions[key] = extension
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def record_supported(body)
|
|
207
|
+
@kinds = body.is_a?(Hash) ? (body['kinds'] || []) : []
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def initialize!
|
|
211
|
+
record_supported(@client.supported)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def scheme_for(network, scheme_name)
|
|
215
|
+
found = scheme_map(@schemes[network], scheme_name)
|
|
216
|
+
return found if found
|
|
217
|
+
|
|
218
|
+
@schemes.each do |pattern, schemes|
|
|
219
|
+
next if pattern == network
|
|
220
|
+
next unless X402.network_matches?(pattern, network)
|
|
221
|
+
|
|
222
|
+
found = scheme_map(schemes, scheme_name)
|
|
223
|
+
return found if found
|
|
224
|
+
end
|
|
225
|
+
nil
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def dynamic_info_fields(key)
|
|
229
|
+
extension = @extensions[key]
|
|
230
|
+
return nil unless extension
|
|
231
|
+
|
|
232
|
+
Product.read(extension, 'dynamicInfoFields') || Product.read(extension, 'dynamic_info_fields')
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def supported_kind?(network, scheme_name)
|
|
236
|
+
@kinds.any? do |kind|
|
|
237
|
+
kind['scheme'] == scheme_name && kind['network'] == network && kind['x402Version'] == 2
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def build_requirements(option, _context)
|
|
242
|
+
scheme_name = Product.read(option, 'scheme')
|
|
243
|
+
network = Product.read(option, 'network')
|
|
244
|
+
scheme = scheme_for(network, scheme_name)
|
|
245
|
+
unless scheme
|
|
246
|
+
raise ArgumentError,
|
|
247
|
+
"No scheme implementation registered for \"#{scheme_name}\" on network \"#{network}\""
|
|
248
|
+
end
|
|
249
|
+
unless supported_kind?(network, scheme_name)
|
|
250
|
+
raise StandardError,
|
|
251
|
+
"Facilitator does not support #{scheme_name} on #{network}. " \
|
|
252
|
+
'Make sure to call initialize() to fetch supported kinds from facilitators.'
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
price = Product.read(option, 'price')
|
|
256
|
+
price = price.call(_context) if price.respond_to?(:call)
|
|
257
|
+
pay_to = Product.read(option, 'payTo')
|
|
258
|
+
pay_to = pay_to.call(_context) if pay_to.respond_to?(:call)
|
|
259
|
+
parsed = call_scheme(scheme, 'parsePrice', price, network)
|
|
260
|
+
parsed = Product.stringify_hash(parsed)
|
|
261
|
+
extra = {}
|
|
262
|
+
extra.merge!(Product.stringify_hash(parsed['extra'])) if parsed['extra'].is_a?(Hash)
|
|
263
|
+
extra.merge!(Product.stringify_hash(Product.read(option, 'extra'))) if Product.read(option, 'extra').is_a?(Hash)
|
|
264
|
+
requirement = {
|
|
265
|
+
'scheme' => scheme_name,
|
|
266
|
+
'network' => network,
|
|
267
|
+
'amount' => parsed['amount'],
|
|
268
|
+
'asset' => parsed['asset'],
|
|
269
|
+
'payTo' => pay_to,
|
|
270
|
+
'maxTimeoutSeconds' => Product.read(option, 'maxTimeoutSeconds') || 300,
|
|
271
|
+
'extra' => extra
|
|
272
|
+
}
|
|
273
|
+
enhanced = call_scheme(scheme, 'enhancePaymentRequirements', requirement, nil, [])
|
|
274
|
+
requirement = Product.stringify_hash(enhanced || requirement)
|
|
275
|
+
resolved = X402.resolve_payment_flow(scheme, requirement)
|
|
276
|
+
requirement['extra'] = X402.apply_payment_flow_wire_extra(requirement['extra'], resolved)
|
|
277
|
+
[requirement]
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def create_payment_required(requirements, resource_info, error, extensions, transport_context)
|
|
281
|
+
accepts = requirements.map do |item|
|
|
282
|
+
copy = Product.stringify_hash(item)
|
|
283
|
+
copy['extra'] = Product.stringify_hash(copy['extra']) if copy['extra'].is_a?(Hash)
|
|
284
|
+
copy
|
|
285
|
+
end
|
|
286
|
+
response = {
|
|
287
|
+
'x402Version' => 2,
|
|
288
|
+
'resource' => resource_info,
|
|
289
|
+
'accepts' => accepts
|
|
290
|
+
}
|
|
291
|
+
response['error'] = error unless error.nil?
|
|
292
|
+
# Match JSON.stringify key order: x402Version, error, resource, accepts, extensions.
|
|
293
|
+
response = reorder_required(response, error)
|
|
294
|
+
if extensions.is_a?(Hash) && !extensions.empty?
|
|
295
|
+
response['extensions'] = extensions
|
|
296
|
+
end
|
|
297
|
+
enrich_extensions(response, transport_context)
|
|
298
|
+
response
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def payment_flow(requirements)
|
|
302
|
+
scheme = scheme_for(requirements['network'], requirements['scheme'])
|
|
303
|
+
raise ArgumentError, "[x402] No server implementation registered for scheme: #{requirements['scheme']}" unless scheme
|
|
304
|
+
|
|
305
|
+
X402.resolve_payment_flow(scheme, requirements)['paymentFlow']
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
private
|
|
309
|
+
|
|
310
|
+
def reorder_required(response, error)
|
|
311
|
+
ordered = { 'x402Version' => response['x402Version'] }
|
|
312
|
+
ordered['error'] = error unless error.nil?
|
|
313
|
+
ordered['resource'] = response['resource']
|
|
314
|
+
ordered['accepts'] = response['accepts']
|
|
315
|
+
ordered
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def enrich_extensions(response, transport_context)
|
|
319
|
+
extensions = response['extensions']
|
|
320
|
+
return unless extensions.is_a?(Hash)
|
|
321
|
+
|
|
322
|
+
extensions.each_key do |key|
|
|
323
|
+
hook = @extensions[key] || @extensions[key.to_s]
|
|
324
|
+
next unless hook.respond_to?(:enrich_payment_required_response)
|
|
325
|
+
|
|
326
|
+
context = {
|
|
327
|
+
'paymentRequiredResponse' => response,
|
|
328
|
+
'transportContext' => transport_context
|
|
329
|
+
}
|
|
330
|
+
shipped = hook.enrich_payment_required_response(extensions[key], context)
|
|
331
|
+
extensions[key] = shipped unless shipped.nil?
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def scheme_map(schemes, scheme_name)
|
|
336
|
+
return nil unless schemes.is_a?(Hash)
|
|
337
|
+
|
|
338
|
+
schemes[scheme_name]
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def call_scheme(scheme, name, *args)
|
|
342
|
+
fn = Product.read(scheme, name) || Product.read(scheme, underscore(name))
|
|
343
|
+
return fn.call(*args) if fn.respond_to?(:call)
|
|
344
|
+
return scheme.public_send(name, *args) if scheme.respond_to?(name)
|
|
345
|
+
return scheme.public_send(underscore(name), *args) if scheme.respond_to?(underscore(name))
|
|
346
|
+
|
|
347
|
+
args.first
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def underscore(name)
|
|
351
|
+
name.gsub(/([A-Z])/) { "_#{Regexp.last_match(1).downcase}" }
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
end
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
=begin
|
|
2
2
|
#Weft API
|
|
3
3
|
|
|
4
|
-
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents
|
|
4
|
+
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents` and `/api/v1/analytics` — are reachable with an `ax_live_*` key but are intentionally left undocumented: they are dashboard-facing and not part of the published client contract. `/api/v1/webhook_endpoints` stays routed and returns HTTP 410 with error code `gone` for index, show, create, update, and destroy. Nothing outside this document is a supported contract, and the response-validation gate in `config/environments/test.rb` enforces only what is declared here. Before claim, a `wbt_*` bearer is temporary and permits only search plus its own status/cancel operations for 30 minutes. Human approval binds it to the User and promotes the same secret to durable identity, search, balance, fetch, purchase-history, status, and revocation capabilities. It remains valid until revoked. Seller, organization, API-key administration, dashboard-session, transfer, withdrawal, and MCP surfaces always refuse it. Bootstrap lifecycle successes follow the API-standard `{ \"data\": ... }` envelope. All errors share the envelope defined by `ErrorResponse`, except the buyer-runtime endpoints (`/search`, `/fetch`) which use bespoke envelopes carrying additional context — see `SearchErrorResponse` and `FetchErrorResponse`.
|
|
5
5
|
|
|
6
|
-
The version of the OpenAPI document: 0.
|
|
6
|
+
The version of the OpenAPI document: 0.32.2
|
|
7
7
|
|
|
8
8
|
Generated by: https://openapi-generator.tech
|
|
9
9
|
Generator version: 7.19.0
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
=begin
|
|
2
2
|
#Weft API
|
|
3
3
|
|
|
4
|
-
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents
|
|
4
|
+
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents` and `/api/v1/analytics` — are reachable with an `ax_live_*` key but are intentionally left undocumented: they are dashboard-facing and not part of the published client contract. `/api/v1/webhook_endpoints` stays routed and returns HTTP 410 with error code `gone` for index, show, create, update, and destroy. Nothing outside this document is a supported contract, and the response-validation gate in `config/environments/test.rb` enforces only what is declared here. Before claim, a `wbt_*` bearer is temporary and permits only search plus its own status/cancel operations for 30 minutes. Human approval binds it to the User and promotes the same secret to durable identity, search, balance, fetch, purchase-history, status, and revocation capabilities. It remains valid until revoked. Seller, organization, API-key administration, dashboard-session, transfer, withdrawal, and MCP surfaces always refuse it. Bootstrap lifecycle successes follow the API-standard `{ \"data\": ... }` envelope. All errors share the envelope defined by `ErrorResponse`, except the buyer-runtime endpoints (`/search`, `/fetch`) which use bespoke envelopes carrying additional context — see `SearchErrorResponse` and `FetchErrorResponse`.
|
|
5
5
|
|
|
6
|
-
The version of the OpenAPI document: 0.
|
|
6
|
+
The version of the OpenAPI document: 0.32.2
|
|
7
7
|
|
|
8
8
|
Generated by: https://openapi-generator.tech
|
|
9
9
|
Generator version: 7.19.0
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
=begin
|
|
2
2
|
#Weft API
|
|
3
3
|
|
|
4
|
-
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents
|
|
4
|
+
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents` and `/api/v1/analytics` — are reachable with an `ax_live_*` key but are intentionally left undocumented: they are dashboard-facing and not part of the published client contract. `/api/v1/webhook_endpoints` stays routed and returns HTTP 410 with error code `gone` for index, show, create, update, and destroy. Nothing outside this document is a supported contract, and the response-validation gate in `config/environments/test.rb` enforces only what is declared here. Before claim, a `wbt_*` bearer is temporary and permits only search plus its own status/cancel operations for 30 minutes. Human approval binds it to the User and promotes the same secret to durable identity, search, balance, fetch, purchase-history, status, and revocation capabilities. It remains valid until revoked. Seller, organization, API-key administration, dashboard-session, transfer, withdrawal, and MCP surfaces always refuse it. Bootstrap lifecycle successes follow the API-standard `{ \"data\": ... }` envelope. All errors share the envelope defined by `ErrorResponse`, except the buyer-runtime endpoints (`/search`, `/fetch`) which use bespoke envelopes carrying additional context — see `SearchErrorResponse` and `FetchErrorResponse`.
|
|
5
5
|
|
|
6
|
-
The version of the OpenAPI document: 0.
|
|
6
|
+
The version of the OpenAPI document: 0.32.2
|
|
7
7
|
|
|
8
8
|
Generated by: https://openapi-generator.tech
|
|
9
9
|
Generator version: 7.19.0
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
=begin
|
|
2
2
|
#Weft API
|
|
3
3
|
|
|
4
|
-
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents
|
|
4
|
+
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents` and `/api/v1/analytics` — are reachable with an `ax_live_*` key but are intentionally left undocumented: they are dashboard-facing and not part of the published client contract. `/api/v1/webhook_endpoints` stays routed and returns HTTP 410 with error code `gone` for index, show, create, update, and destroy. Nothing outside this document is a supported contract, and the response-validation gate in `config/environments/test.rb` enforces only what is declared here. Before claim, a `wbt_*` bearer is temporary and permits only search plus its own status/cancel operations for 30 minutes. Human approval binds it to the User and promotes the same secret to durable identity, search, balance, fetch, purchase-history, status, and revocation capabilities. It remains valid until revoked. Seller, organization, API-key administration, dashboard-session, transfer, withdrawal, and MCP surfaces always refuse it. Bootstrap lifecycle successes follow the API-standard `{ \"data\": ... }` envelope. All errors share the envelope defined by `ErrorResponse`, except the buyer-runtime endpoints (`/search`, `/fetch`) which use bespoke envelopes carrying additional context — see `SearchErrorResponse` and `FetchErrorResponse`.
|
|
5
5
|
|
|
6
|
-
The version of the OpenAPI document: 0.
|
|
6
|
+
The version of the OpenAPI document: 0.32.2
|
|
7
7
|
|
|
8
8
|
Generated by: https://openapi-generator.tech
|
|
9
9
|
Generator version: 7.19.0
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
=begin
|
|
2
2
|
#Weft API
|
|
3
3
|
|
|
4
|
-
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents
|
|
4
|
+
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents` and `/api/v1/analytics` — are reachable with an `ax_live_*` key but are intentionally left undocumented: they are dashboard-facing and not part of the published client contract. `/api/v1/webhook_endpoints` stays routed and returns HTTP 410 with error code `gone` for index, show, create, update, and destroy. Nothing outside this document is a supported contract, and the response-validation gate in `config/environments/test.rb` enforces only what is declared here. Before claim, a `wbt_*` bearer is temporary and permits only search plus its own status/cancel operations for 30 minutes. Human approval binds it to the User and promotes the same secret to durable identity, search, balance, fetch, purchase-history, status, and revocation capabilities. It remains valid until revoked. Seller, organization, API-key administration, dashboard-session, transfer, withdrawal, and MCP surfaces always refuse it. Bootstrap lifecycle successes follow the API-standard `{ \"data\": ... }` envelope. All errors share the envelope defined by `ErrorResponse`, except the buyer-runtime endpoints (`/search`, `/fetch`) which use bespoke envelopes carrying additional context — see `SearchErrorResponse` and `FetchErrorResponse`.
|
|
5
5
|
|
|
6
|
-
The version of the OpenAPI document: 0.
|
|
6
|
+
The version of the OpenAPI document: 0.32.2
|
|
7
7
|
|
|
8
8
|
Generated by: https://openapi-generator.tech
|
|
9
9
|
Generator version: 7.19.0
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
=begin
|
|
2
2
|
#Weft API
|
|
3
3
|
|
|
4
|
-
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents
|
|
4
|
+
#The Weft API powers the `weft` CLI, the hosted MCP server (`weft.network/mcp`), and third-party applications that discover and pay for resources on Weft. The buyer runtime covers six concerns: 1. Account creation and recovery (`/api/v1/auth/*`) 2. Credential identity (`/api/v1/me`) 3. Wallet visibility (`/api/v1/balance`) 4. Discovery (`/api/v1/search`) 5. Paid execution (`/api/v1/fetch`) 6. Purchase history (`/api/v1/purchases`) Buyer runtime calls require a dashboard-created `wk_*` account key, an OAuth access token with the relevant scope, or a claimed `wbt_*` bearer on its fixed allowlist. The organization-scoped API key and payment operations in this document are seller administration surfaces and require an `ax_live_*` resource key. These credential types are not interchangeable. This document is a deliberate subset of the `/api/v1` surface, not an inventory of it. The seller-side management endpoints — `/api/v1/agents` and `/api/v1/analytics` — are reachable with an `ax_live_*` key but are intentionally left undocumented: they are dashboard-facing and not part of the published client contract. `/api/v1/webhook_endpoints` stays routed and returns HTTP 410 with error code `gone` for index, show, create, update, and destroy. Nothing outside this document is a supported contract, and the response-validation gate in `config/environments/test.rb` enforces only what is declared here. Before claim, a `wbt_*` bearer is temporary and permits only search plus its own status/cancel operations for 30 minutes. Human approval binds it to the User and promotes the same secret to durable identity, search, balance, fetch, purchase-history, status, and revocation capabilities. It remains valid until revoked. Seller, organization, API-key administration, dashboard-session, transfer, withdrawal, and MCP surfaces always refuse it. Bootstrap lifecycle successes follow the API-standard `{ \"data\": ... }` envelope. All errors share the envelope defined by `ErrorResponse`, except the buyer-runtime endpoints (`/search`, `/fetch`) which use bespoke envelopes carrying additional context — see `SearchErrorResponse` and `FetchErrorResponse`.
|
|
5
5
|
|
|
6
|
-
The version of the OpenAPI document: 0.
|
|
6
|
+
The version of the OpenAPI document: 0.32.2
|
|
7
7
|
|
|
8
8
|
Generated by: https://openapi-generator.tech
|
|
9
9
|
Generator version: 7.19.0
|