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.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/docs/FetchApi.md +3 -3
  3. data/docs/FetchErrorResponse.md +1 -1
  4. data/docs/FetchRequest.md +6 -2
  5. data/docs/FetchResponse.md +5 -3
  6. data/docs/GetPurchaseIdParameter.md +48 -0
  7. data/docs/PaymentsApi.md +2 -0
  8. data/docs/Purchase.md +6 -0
  9. data/docs/PurchasesApi.md +2 -2
  10. data/docs/SearchApi.md +1 -1
  11. data/docs/SearchCompactAccess.md +23 -0
  12. data/docs/SearchCompactAccessPrice.md +23 -0
  13. data/docs/SearchCompactNextCall.md +23 -0
  14. data/docs/SearchCompactResult.md +47 -0
  15. data/docs/SearchCompactResultAttribution.md +21 -0
  16. data/docs/SearchCompactResultBlockedScopesInner.md +19 -0
  17. data/docs/SearchCompactResultOperation.md +21 -0
  18. data/docs/SearchCompactResultProvider.md +19 -0
  19. data/docs/SearchEndpointCall.md +1 -1
  20. data/docs/SearchEndpointCallInputSchema.md +14 -0
  21. data/docs/SearchEndpointHit.md +5 -1
  22. data/docs/SearchHelperDocs.md +23 -0
  23. data/docs/SearchRequest.md +3 -1
  24. data/docs/SearchResponse.md +9 -3
  25. data/docs/SearchWeftFetchCompatibility.md +3 -1
  26. data/docs/WebhooksApi.md +414 -0
  27. data/lib/weft/client.rb +271 -0
  28. data/lib/weft/error.rb +41 -0
  29. data/lib/weft/facilitator/client.rb +179 -42
  30. data/lib/weft/facilitator/echo.rb +99 -0
  31. data/lib/weft/facilitator/extensions.rb +183 -0
  32. data/lib/weft/facilitator/fee.rb +26 -11
  33. data/lib/weft/facilitator/handshake.rb +92 -0
  34. data/lib/weft/facilitator/json_wire.rb +74 -0
  35. data/lib/weft/facilitator/middleware.rb +562 -137
  36. data/lib/weft/facilitator/path_match.rb +179 -0
  37. data/lib/weft/facilitator/product.rb +380 -0
  38. data/lib/weft/facilitator/replay.rb +46 -0
  39. data/lib/weft/facilitator/settlement.rb +117 -0
  40. data/lib/weft/facilitator/x402.rb +355 -0
  41. data/lib/weft/generated/api/account_api.rb +2 -2
  42. data/lib/weft/generated/api/agent_bootstrap_api.rb +2 -2
  43. data/lib/weft/generated/api/api_keys_api.rb +2 -2
  44. data/lib/weft/generated/api/auth_api.rb +2 -2
  45. data/lib/weft/generated/api/balance_api.rb +2 -2
  46. data/lib/weft/generated/api/documentation_api.rb +2 -2
  47. data/lib/weft/generated/api/fetch_api.rb +6 -6
  48. data/lib/weft/generated/api/payments_api.rb +4 -2
  49. data/lib/weft/generated/api/purchases_api.rb +4 -4
  50. data/lib/weft/generated/api/resources_api.rb +2 -2
  51. data/lib/weft/generated/api/search_api.rb +4 -4
  52. data/lib/weft/generated/api/webhooks_api.rb +388 -0
  53. data/lib/weft/generated/api_client.rb +2 -2
  54. data/lib/weft/generated/api_error.rb +2 -2
  55. data/lib/weft/generated/api_model_base.rb +2 -2
  56. data/lib/weft/generated/configuration.rb +2 -2
  57. data/lib/weft/generated/models/account_bootstrap_approval.rb +2 -2
  58. data/lib/weft/generated/models/account_bootstrap_created.rb +2 -2
  59. data/lib/weft/generated/models/account_bootstrap_created_approval.rb +2 -2
  60. data/lib/weft/generated/models/account_bootstrap_created_response.rb +2 -2
  61. data/lib/weft/generated/models/account_bootstrap_request.rb +2 -2
  62. data/lib/weft/generated/models/account_bootstrap_status.rb +2 -2
  63. data/lib/weft/generated/models/account_bootstrap_status_response.rb +2 -2
  64. data/lib/weft/generated/models/account_details.rb +2 -2
  65. data/lib/weft/generated/models/api_key.rb +2 -2
  66. data/lib/weft/generated/models/api_key_created.rb +2 -2
  67. data/lib/weft/generated/models/api_key_created_response.rb +2 -2
  68. data/lib/weft/generated/models/api_key_list_response.rb +2 -2
  69. data/lib/weft/generated/models/auth_response.rb +2 -2
  70. data/lib/weft/generated/models/auth_response_data.rb +2 -2
  71. data/lib/weft/generated/models/balance_response.rb +2 -2
  72. data/lib/weft/generated/models/confirm_request.rb +2 -2
  73. data/lib/weft/generated/models/create_api_key_request.rb +2 -2
  74. data/lib/weft/generated/models/enrolled_resource.rb +2 -2
  75. data/lib/weft/generated/models/error.rb +2 -2
  76. data/lib/weft/generated/models/error_response.rb +2 -2
  77. data/lib/weft/generated/models/fetch403_response.rb +2 -2
  78. data/lib/weft/generated/models/fetch_balance_snapshot.rb +2 -2
  79. data/lib/weft/generated/models/fetch_error_response.rb +5 -5
  80. data/lib/weft/generated/models/fetch_request.rb +46 -5
  81. data/lib/weft/generated/models/fetch_request_body.rb +2 -2
  82. data/lib/weft/generated/models/fetch_response.rb +36 -64
  83. data/lib/weft/generated/models/get_purchase_id_parameter.rb +104 -0
  84. data/lib/weft/generated/models/insufficient_scope_response.rb +2 -2
  85. data/lib/weft/generated/models/me_api_key.rb +2 -2
  86. data/lib/weft/generated/models/me_api_key_creator.rb +2 -2
  87. data/lib/weft/generated/models/me_response.rb +2 -2
  88. data/lib/weft/generated/models/me_response_data.rb +2 -2
  89. data/lib/weft/generated/models/message_response.rb +2 -2
  90. data/lib/weft/generated/models/message_response_data.rb +2 -2
  91. data/lib/weft/generated/models/pagination.rb +2 -2
  92. data/lib/weft/generated/models/password_reset_request.rb +2 -2
  93. data/lib/weft/generated/models/password_update_request.rb +2 -2
  94. data/lib/weft/generated/models/payment.rb +2 -2
  95. data/lib/weft/generated/models/payment_list_response.rb +2 -2
  96. data/lib/weft/generated/models/payment_response.rb +2 -2
  97. data/lib/weft/generated/models/principal_wallet.rb +2 -2
  98. data/lib/weft/generated/models/promo_balance.rb +2 -2
  99. data/lib/weft/generated/models/purchase.rb +75 -3
  100. data/lib/weft/generated/models/purchase_artifact.rb +2 -2
  101. data/lib/weft/generated/models/purchase_list_response.rb +2 -2
  102. data/lib/weft/generated/models/purchase_response.rb +2 -2
  103. data/lib/weft/generated/models/rate_limit_response.rb +2 -2
  104. data/lib/weft/generated/models/resend_confirmation_request.rb +2 -2
  105. data/lib/weft/generated/models/resource_enrollment_request.rb +2 -2
  106. data/lib/weft/generated/models/resource_enrollment_response.rb +2 -2
  107. data/lib/weft/generated/models/resource_stats.rb +2 -2
  108. data/lib/weft/generated/models/search_access_method.rb +2 -2
  109. data/lib/weft/generated/models/search_capability_ref.rb +2 -2
  110. data/lib/weft/generated/models/search_compact_access.rb +179 -0
  111. data/lib/weft/generated/models/search_compact_access_price.rb +176 -0
  112. data/lib/weft/generated/models/search_compact_next_call.rb +275 -0
  113. data/lib/weft/generated/models/search_compact_result.rb +389 -0
  114. data/lib/weft/generated/models/search_compact_result_attribution.rb +166 -0
  115. data/lib/weft/generated/models/search_compact_result_blocked_scopes_inner.rb +156 -0
  116. data/lib/weft/generated/models/search_compact_result_operation.rb +183 -0
  117. data/lib/weft/generated/models/search_compact_result_provider.rb +156 -0
  118. data/lib/weft/generated/models/search_curated_callability.rb +2 -2
  119. data/lib/weft/generated/models/search_curated_execution.rb +2 -2
  120. data/lib/weft/generated/models/search_curated_operation.rb +2 -2
  121. data/lib/weft/generated/models/search_curated_service.rb +2 -2
  122. data/lib/weft/generated/models/search_curated_source.rb +2 -2
  123. data/lib/weft/generated/models/search_endpoint_call.rb +4 -4
  124. data/lib/weft/generated/models/search_endpoint_call_input_schema.rb +103 -0
  125. data/lib/weft/generated/models/search_endpoint_hit.rb +25 -6
  126. data/lib/weft/generated/models/search_endpoint_price.rb +2 -2
  127. data/lib/weft/generated/models/search_error_response.rb +4 -4
  128. data/lib/weft/generated/models/search_execution_mode_filter.rb +2 -2
  129. data/lib/weft/generated/models/search_filter_spec.rb +2 -2
  130. data/lib/weft/generated/models/search_helper_docs.rb +175 -0
  131. data/lib/weft/generated/models/search_method_filter.rb +2 -2
  132. data/lib/weft/generated/models/search_payment_offer.rb +2 -2
  133. data/lib/weft/generated/models/search_price_atomic_filter.rb +2 -2
  134. data/lib/weft/generated/models/search_price_usd_filter.rb +2 -2
  135. data/lib/weft/generated/models/search_protocol_filter.rb +2 -2
  136. data/lib/weft/generated/models/search_provider_ref.rb +2 -2
  137. data/lib/weft/generated/models/search_request.rb +50 -6
  138. data/lib/weft/generated/models/search_resource_type_filter.rb +2 -2
  139. data/lib/weft/generated/models/search_response.rb +71 -8
  140. data/lib/weft/generated/models/search_response_warnings_inner.rb +2 -2
  141. data/lib/weft/generated/models/search_result.rb +2 -2
  142. data/lib/weft/generated/models/search_string_set_filter.rb +2 -2
  143. data/lib/weft/generated/models/search_weft_fetch_compatibility.rb +28 -6
  144. data/lib/weft/generated/models/sign_in_request.rb +2 -2
  145. data/lib/weft/generated/models/sign_up_request.rb +2 -2
  146. data/lib/weft/generated/models/spending_policy.rb +2 -2
  147. data/lib/weft/generated/models/user.rb +2 -2
  148. data/lib/weft/generated/models/user_principal.rb +2 -2
  149. data/lib/weft/generated/models/wallet.rb +2 -2
  150. data/lib/weft/generated/version.rb +3 -3
  151. data/lib/weft/sdk.rb +3 -1
  152. metadata +39 -4
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../generated/version'
4
+ require_relative 'json_wire'
5
+ require_relative 'product'
6
+
7
+ module Weft
8
+ module Facilitator
9
+ WEFT_DECLARED_HEADER = 'X-Weft-Declared'
10
+ WEFT_API_KEY_HEADER = 'X-API-Key'
11
+ HEADER_SAFE = /\A[\x21-\x7e]+\z/
12
+ ADAPTER_NAME = 'rack'
13
+
14
+ module Handshake
15
+ module_function
16
+
17
+ def build_auth_headers(adapter, api_key, declaration)
18
+ declaration = stringify_declaration(declaration)
19
+ key = resolve_api_key(api_key)
20
+ supported = {
21
+ 'User-Agent' => "weft-sdk-#{adapter}/#{sdk_version}"
22
+ }
23
+ supported['Authorization'] = "Bearer #{key}" unless key.nil?
24
+
25
+ declared = declared_identity_value(declaration)
26
+ supported[WEFT_DECLARED_HEADER] = declared unless declared.nil?
27
+
28
+ headers = { 'supported' => supported }
29
+ unless key.nil?
30
+ headers['settle'] = { WEFT_API_KEY_HEADER => key }
31
+ headers['verify'] = { WEFT_API_KEY_HEADER => key }
32
+ end
33
+ headers
34
+ end
35
+
36
+ def declared_identity_value(declaration)
37
+ declared = Product.sanitize_product_identity(declaration)
38
+ dimensions = Product.resolve_dimensions(declaration['dimensions'], Product.create_warn)
39
+ payload = {}
40
+ payload['name'] = declared['name'] if declared.key?('name')
41
+ payload['type'] = declared['type'] if declared.key?('type')
42
+ payload['tags'] = declared['tags'] if declared.key?('tags')
43
+ payload['icon_url'] = declared['iconUrl'] if declared.key?('iconUrl')
44
+ payload['dimensions'] = dimensions unless dimensions.nil?
45
+ return nil if payload.empty?
46
+
47
+ JsonWire.base64url_encode(JsonWire.generate(payload))
48
+ end
49
+
50
+ def resolve_api_key(api_key)
51
+ return nil if api_key.nil?
52
+ unless api_key.is_a?(String)
53
+ warn "[weft] ignoring apiKey: expected a string, got #{js_type(api_key)}"
54
+ return nil
55
+ end
56
+
57
+ trimmed = api_key.strip
58
+ if trimmed.empty?
59
+ warn '[weft] ignoring empty apiKey'
60
+ return nil
61
+ end
62
+ unless HEADER_SAFE.match?(trimmed)
63
+ warn '[weft] ignoring apiKey: it contains whitespace or non-printable ' \
64
+ 'characters that cannot travel in an HTTP header'
65
+ return nil
66
+ end
67
+
68
+ trimmed
69
+ end
70
+
71
+ def stringify_declaration(declaration)
72
+ return {} unless declaration.is_a?(Hash)
73
+
74
+ declaration.each_with_object({}) do |(key, value), out|
75
+ out[key.to_s] = value
76
+ end
77
+ end
78
+
79
+ def sdk_version
80
+ defined?(SDK) ? SDK::VERSION : VERSION
81
+ end
82
+
83
+ def js_type(value)
84
+ case value
85
+ when Integer, Float then 'number'
86
+ when TrueClass, FalseClass then 'boolean'
87
+ else 'object'
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'base64'
4
+ require 'json'
5
+
6
+ module Weft
7
+ module Facilitator
8
+ # JSON.stringify and the two base64 forms @x402/core puts on the wire.
9
+ module JsonWire
10
+ module_function
11
+
12
+ def generate(value)
13
+ return nil if circular?(value)
14
+
15
+ JSON.generate(sanitize(value))
16
+ rescue JSON::GeneratorError, JSON::NestingError
17
+ nil
18
+ end
19
+
20
+ def circular?(value, seen = {})
21
+ case value
22
+ when Hash, Array
23
+ return true if seen[value.object_id]
24
+
25
+ seen[value.object_id] = true
26
+ children = value.is_a?(Hash) ? value.values : value
27
+ children.any? { |item| circular?(item, seen) }
28
+ else
29
+ false
30
+ end
31
+ end
32
+
33
+ def sanitize(value)
34
+ case value
35
+ when Hash
36
+ value.each_with_object({}) do |(key, item), out|
37
+ out[key.is_a?(Symbol) ? key.to_s : key] = sanitize(item)
38
+ end
39
+ when Array
40
+ value.map { |item| sanitize(item) }
41
+ when Float
42
+ value.finite? ? value : nil
43
+ else
44
+ value
45
+ end
46
+ end
47
+
48
+ def base64_encode(text)
49
+ Base64.strict_encode64(text.b)
50
+ end
51
+
52
+ def base64_decode(text)
53
+ Base64.strict_decode64(text).force_encoding(Encoding::UTF_8)
54
+ end
55
+
56
+ def base64url_encode(text)
57
+ Base64.urlsafe_encode64(text.b, padding: false)
58
+ end
59
+
60
+ def base64url_decode(text)
61
+ padded = text.tr('-_', '+/')
62
+ padded += '=' * ((4 - (padded.length % 4)) % 4)
63
+ Base64.decode64(padded).force_encoding(Encoding::UTF_8)
64
+ end
65
+
66
+ def encode_json(value)
67
+ json = generate(value)
68
+ raise ArgumentError, 'value is not JSON' if json.nil?
69
+
70
+ base64_encode(json)
71
+ end
72
+ end
73
+ end
74
+ end