@antseed/node 0.2.156 → 0.2.158

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 (179) hide show
  1. package/dist/discovery/announcer.d.ts +16 -1
  2. package/dist/discovery/announcer.d.ts.map +1 -1
  3. package/dist/discovery/announcer.js +69 -9
  4. package/dist/discovery/announcer.js.map +1 -1
  5. package/dist/discovery/http-metadata-resolver.d.ts +1 -1
  6. package/dist/discovery/http-metadata-resolver.d.ts.map +1 -1
  7. package/dist/discovery/http-metadata-resolver.js +7 -1
  8. package/dist/discovery/http-metadata-resolver.js.map +1 -1
  9. package/dist/discovery/index.d.ts +3 -2
  10. package/dist/discovery/index.d.ts.map +1 -1
  11. package/dist/discovery/index.js +2 -1
  12. package/dist/discovery/index.js.map +1 -1
  13. package/dist/discovery/metadata/define-version.d.ts +40 -0
  14. package/dist/discovery/metadata/define-version.d.ts.map +1 -0
  15. package/dist/discovery/metadata/define-version.js +104 -0
  16. package/dist/discovery/metadata/define-version.js.map +1 -0
  17. package/dist/discovery/metadata/field.d.ts +26 -0
  18. package/dist/discovery/metadata/field.d.ts.map +1 -0
  19. package/dist/discovery/metadata/field.js +2 -0
  20. package/dist/discovery/metadata/field.js.map +1 -0
  21. package/dist/discovery/metadata/fields/offerings.d.ts +7 -0
  22. package/dist/discovery/metadata/fields/offerings.d.ts.map +1 -0
  23. package/dist/discovery/metadata/fields/offerings.js +52 -0
  24. package/dist/discovery/metadata/fields/offerings.js.map +1 -0
  25. package/dist/discovery/metadata/fields/on-chain-stats.d.ts +6 -0
  26. package/dist/discovery/metadata/fields/on-chain-stats.d.ts.map +1 -0
  27. package/dist/discovery/metadata/fields/on-chain-stats.js +30 -0
  28. package/dist/discovery/metadata/fields/on-chain-stats.js.map +1 -0
  29. package/dist/discovery/metadata/fields/peer-capabilities.d.ts +4 -0
  30. package/dist/discovery/metadata/fields/peer-capabilities.d.ts.map +1 -0
  31. package/dist/discovery/metadata/fields/peer-capabilities.js +21 -0
  32. package/dist/discovery/metadata/fields/peer-capabilities.js.map +1 -0
  33. package/dist/discovery/metadata/fields/peer-profile.d.ts +11 -0
  34. package/dist/discovery/metadata/fields/peer-profile.d.ts.map +1 -0
  35. package/dist/discovery/metadata/fields/peer-profile.js +58 -0
  36. package/dist/discovery/metadata/fields/peer-profile.js.map +1 -0
  37. package/dist/discovery/metadata/fields/provider-basics.d.ts +12 -0
  38. package/dist/discovery/metadata/fields/provider-basics.d.ts.map +1 -0
  39. package/dist/discovery/metadata/fields/provider-basics.js +87 -0
  40. package/dist/discovery/metadata/fields/provider-basics.js.map +1 -0
  41. package/dist/discovery/metadata/fields/service-api-protocols.d.ts +4 -0
  42. package/dist/discovery/metadata/fields/service-api-protocols.d.ts.map +1 -0
  43. package/dist/discovery/metadata/fields/service-api-protocols.js +40 -0
  44. package/dist/discovery/metadata/fields/service-api-protocols.js.map +1 -0
  45. package/dist/discovery/metadata/fields/service-capabilities.d.ts +7 -0
  46. package/dist/discovery/metadata/fields/service-capabilities.d.ts.map +1 -0
  47. package/dist/discovery/metadata/fields/service-capabilities.js +229 -0
  48. package/dist/discovery/metadata/fields/service-capabilities.js.map +1 -0
  49. package/dist/discovery/metadata/fields/service-categories.d.ts +4 -0
  50. package/dist/discovery/metadata/fields/service-categories.d.ts.map +1 -0
  51. package/dist/discovery/metadata/fields/service-categories.js +37 -0
  52. package/dist/discovery/metadata/fields/service-categories.js.map +1 -0
  53. package/dist/discovery/metadata/fields/service-health.d.ts +7 -0
  54. package/dist/discovery/metadata/fields/service-health.d.ts.map +1 -0
  55. package/dist/discovery/metadata/fields/service-health.js +90 -0
  56. package/dist/discovery/metadata/fields/service-health.js.map +1 -0
  57. package/dist/discovery/metadata/fields/service-performance.d.ts +7 -0
  58. package/dist/discovery/metadata/fields/service-performance.d.ts.map +1 -0
  59. package/dist/discovery/metadata/fields/service-performance.js +63 -0
  60. package/dist/discovery/metadata/fields/service-performance.js.map +1 -0
  61. package/dist/discovery/metadata/fields/service-unit-billing.d.ts +8 -0
  62. package/dist/discovery/metadata/fields/service-unit-billing.d.ts.map +1 -0
  63. package/dist/discovery/metadata/fields/service-unit-billing.js +81 -0
  64. package/dist/discovery/metadata/fields/service-unit-billing.js.map +1 -0
  65. package/dist/discovery/metadata/fields/verifications.d.ts +7 -0
  66. package/dist/discovery/metadata/fields/verifications.d.ts.map +1 -0
  67. package/dist/discovery/metadata/fields/verifications.js +96 -0
  68. package/dist/discovery/metadata/fields/verifications.js.map +1 -0
  69. package/dist/discovery/metadata/index.d.ts +27 -0
  70. package/dist/discovery/metadata/index.d.ts.map +1 -0
  71. package/dist/discovery/metadata/index.js +56 -0
  72. package/dist/discovery/metadata/index.js.map +1 -0
  73. package/dist/discovery/metadata/versions/v10.d.ts +5 -0
  74. package/dist/discovery/metadata/versions/v10.d.ts.map +1 -0
  75. package/dist/discovery/metadata/versions/v10.js +32 -0
  76. package/dist/discovery/metadata/versions/v10.js.map +1 -0
  77. package/dist/discovery/metadata/versions/v11.d.ts +5 -0
  78. package/dist/discovery/metadata/versions/v11.d.ts.map +1 -0
  79. package/dist/discovery/metadata/versions/v11.js +11 -0
  80. package/dist/discovery/metadata/versions/v11.js.map +1 -0
  81. package/dist/discovery/metadata/versions/v12.d.ts +5 -0
  82. package/dist/discovery/metadata/versions/v12.d.ts.map +1 -0
  83. package/dist/discovery/metadata/versions/v12.js +66 -0
  84. package/dist/discovery/metadata/versions/v12.js.map +1 -0
  85. package/dist/discovery/metadata/versions/v13.d.ts +5 -0
  86. package/dist/discovery/metadata/versions/v13.d.ts.map +1 -0
  87. package/dist/discovery/metadata/versions/v13.js +16 -0
  88. package/dist/discovery/metadata/versions/v13.js.map +1 -0
  89. package/dist/discovery/metadata/versions/v14.d.ts +5 -0
  90. package/dist/discovery/metadata/versions/v14.d.ts.map +1 -0
  91. package/dist/discovery/metadata/versions/v14.js +16 -0
  92. package/dist/discovery/metadata/versions/v14.js.map +1 -0
  93. package/dist/discovery/metadata/wire.d.ts +54 -0
  94. package/dist/discovery/metadata/wire.d.ts.map +1 -0
  95. package/dist/discovery/metadata/wire.js +149 -0
  96. package/dist/discovery/metadata/wire.js.map +1 -0
  97. package/dist/discovery/metadata-codec.d.ts +1 -38
  98. package/dist/discovery/metadata-codec.d.ts.map +1 -1
  99. package/dist/discovery/metadata-codec.js +3 -1154
  100. package/dist/discovery/metadata-codec.js.map +1 -1
  101. package/dist/discovery/metadata-server.d.ts +3 -2
  102. package/dist/discovery/metadata-server.d.ts.map +1 -1
  103. package/dist/discovery/metadata-server.js +4 -1
  104. package/dist/discovery/metadata-server.js.map +1 -1
  105. package/dist/discovery/metadata-validator.d.ts.map +1 -1
  106. package/dist/discovery/metadata-validator.js +90 -1
  107. package/dist/discovery/metadata-validator.js.map +1 -1
  108. package/dist/discovery/service-catalog.d.ts +16 -2
  109. package/dist/discovery/service-catalog.d.ts.map +1 -1
  110. package/dist/discovery/service-catalog.js +8 -1
  111. package/dist/discovery/service-catalog.js.map +1 -1
  112. package/dist/health/gas-auto-refuel.d.ts +138 -0
  113. package/dist/health/gas-auto-refuel.d.ts.map +1 -0
  114. package/dist/health/gas-auto-refuel.js +216 -0
  115. package/dist/health/gas-auto-refuel.js.map +1 -0
  116. package/dist/health/gas-health-monitor.d.ts +4 -0
  117. package/dist/health/gas-health-monitor.d.ts.map +1 -1
  118. package/dist/health/gas-health-monitor.js +13 -0
  119. package/dist/health/gas-health-monitor.js.map +1 -1
  120. package/dist/health/model-health-checker.d.ts +67 -33
  121. package/dist/health/model-health-checker.d.ts.map +1 -1
  122. package/dist/health/model-health-checker.js +273 -121
  123. package/dist/health/model-health-checker.js.map +1 -1
  124. package/dist/health/self-health-error.d.ts +20 -0
  125. package/dist/health/self-health-error.d.ts.map +1 -0
  126. package/dist/health/self-health-error.js +60 -0
  127. package/dist/health/self-health-error.js.map +1 -0
  128. package/dist/health/seller-events.d.ts +1 -1
  129. package/dist/health/seller-events.d.ts.map +1 -1
  130. package/dist/health/seller-events.js.map +1 -1
  131. package/dist/health/service-performance.d.ts +28 -0
  132. package/dist/health/service-performance.d.ts.map +1 -0
  133. package/dist/health/service-performance.js +144 -0
  134. package/dist/health/service-performance.js.map +1 -0
  135. package/dist/health/stream-outcome.d.ts +19 -0
  136. package/dist/health/stream-outcome.d.ts.map +1 -0
  137. package/dist/health/stream-outcome.js +91 -0
  138. package/dist/health/stream-outcome.js.map +1 -0
  139. package/dist/index.d.ts +8 -5
  140. package/dist/index.d.ts.map +1 -1
  141. package/dist/index.js +6 -3
  142. package/dist/index.js.map +1 -1
  143. package/dist/interfaces/seller-provider.d.ts +11 -5
  144. package/dist/interfaces/seller-provider.d.ts.map +1 -1
  145. package/dist/node.d.ts +10 -2
  146. package/dist/node.d.ts.map +1 -1
  147. package/dist/node.js +43 -89
  148. package/dist/node.js.map +1 -1
  149. package/dist/p2p/connection-manager.d.ts +5 -1
  150. package/dist/p2p/connection-manager.d.ts.map +1 -1
  151. package/dist/p2p/connection-manager.js +48 -13
  152. package/dist/p2p/connection-manager.js.map +1 -1
  153. package/dist/payments/chain-config.d.ts +11 -0
  154. package/dist/payments/chain-config.d.ts.map +1 -1
  155. package/dist/payments/chain-config.js +7 -0
  156. package/dist/payments/chain-config.js.map +1 -1
  157. package/dist/payments/evm/usdc-eth-swap-client.d.ts +45 -0
  158. package/dist/payments/evm/usdc-eth-swap-client.d.ts.map +1 -0
  159. package/dist/payments/evm/usdc-eth-swap-client.js +83 -0
  160. package/dist/payments/evm/usdc-eth-swap-client.js.map +1 -0
  161. package/dist/payments/index.d.ts +2 -0
  162. package/dist/payments/index.d.ts.map +1 -1
  163. package/dist/payments/index.js +2 -0
  164. package/dist/payments/index.js.map +1 -1
  165. package/dist/payments/seller-payment-manager.d.ts +50 -0
  166. package/dist/payments/seller-payment-manager.d.ts.map +1 -1
  167. package/dist/payments/seller-payment-manager.js +320 -80
  168. package/dist/payments/seller-payment-manager.js.map +1 -1
  169. package/dist/routing/seller-health.d.ts +21 -0
  170. package/dist/routing/seller-health.d.ts.map +1 -1
  171. package/dist/routing/seller-health.js +19 -3
  172. package/dist/routing/seller-health.js.map +1 -1
  173. package/dist/seller-request-handler.d.ts +14 -0
  174. package/dist/seller-request-handler.d.ts.map +1 -1
  175. package/dist/seller-request-handler.js +207 -30
  176. package/dist/seller-request-handler.js.map +1 -1
  177. package/dist/types/peer.d.ts +6 -2
  178. package/dist/types/peer.d.ts.map +1 -1
  179. package/package.json +3 -3
@@ -1,1155 +1,4 @@
1
- import { SERVICE_CAPABILITY_MODALITIES, VIDEO_INPUT_KINDS } from "./peer-metadata.js";
2
- import { hexToBytes, bytesToHex } from "../utils/hex.js";
3
- import { toPeerId } from "../types/peer.js";
4
- import { WELL_KNOWN_SERVICE_API_PROTOCOLS, isKnownServiceApiProtocol } from "../types/service-api.js";
5
- import { UNIT_BILLING_MATCH_KEYS_V1, UNIT_BILLING_UNITS_V1, } from "../types/billing.js";
6
- const SERVICE_CATEGORIES_METADATA_VERSION = 3;
7
- const SERVICE_API_PROTOCOLS_METADATA_VERSION = 4;
8
- const PUBLIC_ADDRESS_METADATA_VERSION = 5;
9
- const SELLER_CONTRACT_METADATA_VERSION = 8;
10
- const DOMAIN_VERIFICATION_METADATA_VERSION = 9;
11
- const PEER_CAPABILITIES_METADATA_VERSION = 10;
12
- const DOMAIN_VERIFICATION_METHOD_IDS = {
13
- "dns-txt": 0,
14
- "https-well-known": 1,
15
- };
16
- const DOMAIN_VERIFICATION_METHODS_BY_ID = ["dns-txt", "https-well-known"];
17
- const SERVICE_UNIT_BILLING_METADATA_VERSION = 11;
18
- const SERVICE_CAPABILITIES_METADATA_VERSION = 12;
19
- const WIDE_SERVICE_COUNTS_METADATA_VERSION = 12;
20
- const UNIT_BILLING_UNITS_BY_ID = [...UNIT_BILLING_UNITS_V1];
21
- const UNIT_BILLING_UNIT_IDS = new Map(UNIT_BILLING_UNITS_BY_ID.map((unit, index) => [unit, index]));
22
- const UNIT_BILLING_MATCH_KEYS_BY_ID = [...UNIT_BILLING_MATCH_KEYS_V1];
23
- const UNIT_BILLING_MATCH_KEY_IDS = new Map(UNIT_BILLING_MATCH_KEYS_BY_ID.map((key, index) => [key, index]));
24
- /**
25
- * Encode metadata into binary format:
26
- * [version:1][peerId:20][regionLen:1][region:N][timestamp:8 BigUint64][providerCount:1]
27
- * for each provider:
28
- * [providerLen:1][provider:N][serviceCount:1|2][services...]
29
- * [defaultInputPrice:4][defaultOutputPrice:4][defaultCachedInputPrice:4]
30
- * [servicePricingCount:1|2][servicePricingEntries...]
31
- * [serviceCategoryCount:1|2][serviceCategoryEntries...] (v3+ only)
32
- * [serviceApiProtocolCount:1|2][serviceApiProtocolEntries...] (v4+ only)
33
- * [maxConcurrency:2][currentLoad:2]
34
- * servicePricingEntry: [serviceLen:1][service:N][inputPrice:4][outputPrice:4][cachedInputPrice:4]
35
- * serviceCategoryEntry(v3+): [serviceLen:1][service:N][categoryCount:1][categories...]
36
- * category(v3+): [categoryLen:1][category:N]
37
- * serviceApiProtocolEntry(v4+): [serviceLen:1][service:N][protocolCount:1][protocols...]
38
- * protocol(v4+): [protocolLen:1][protocol:N]
39
- * [displayNameFlag:1][displayNameLen:1][displayName:N] (v3+ only)
40
- * [publicAddressFlag:1][publicAddressLen:1][publicAddress:N] (v5+ only)
41
- * [sellerContractFlag:1][sellerContract:20] (v8+ only)
42
- * [domainVerificationCount:1][domainVerificationEntries...] (v9+ only)
43
- * domainVerificationEntry(v9+): [domainLen:1][domain:N][methodCount:1][methodIds...]
44
- * [githubVerificationCount:1][githubVerificationEntries...] (v9+ only)
45
- * githubVerificationEntry(v9+): [usernameLen:1][username:N][repoLen:1][repo:N] (repoLen 0 = profile repo)
46
- * [offerings...]
47
- * [onChainStatsFlag:1][onChainStats:10]
48
- * [capabilityCount:1][capabilities...] (v10+ only)
49
- * capability(v10+): [capabilityLen:1][capability:N]
50
- * [signature:65]
51
- */
52
- export function encodeMetadata(metadata) {
53
- const bodyBytes = encodeBody(metadata);
54
- const signatureBytes = hexToBytes(metadata.signature);
55
- const result = new Uint8Array(bodyBytes.length + signatureBytes.length);
56
- result.set(bodyBytes, 0);
57
- result.set(signatureBytes, bodyBytes.length);
58
- return result;
59
- }
60
- /**
61
- * Encode metadata without signature, for signing purposes.
62
- */
63
- export function encodeMetadataForSigning(metadata) {
64
- return encodeBody(metadata);
65
- }
66
- function encodeBody(metadata) {
67
- const parts = [];
68
- const hasServiceCategoryExtensions = metadata.version >= SERVICE_CATEGORIES_METADATA_VERSION;
69
- const hasServiceApiProtocolExtensions = metadata.version >= SERVICE_API_PROTOCOLS_METADATA_VERSION;
70
- const hasWideServiceCounts = metadata.version >= WIDE_SERVICE_COUNTS_METADATA_VERSION;
71
- // version: 1 byte
72
- parts.push(new Uint8Array([metadata.version]));
73
- // peerId: 20 bytes (EVM address)
74
- parts.push(hexToBytes(metadata.peerId));
75
- // region: length-prefixed
76
- const regionBytes = new TextEncoder().encode(metadata.region);
77
- parts.push(new Uint8Array([regionBytes.length]));
78
- parts.push(regionBytes);
79
- // timestamp: 8 bytes BigUint64
80
- const timestampBuf = new ArrayBuffer(8);
81
- const timestampView = new DataView(timestampBuf);
82
- timestampView.setBigUint64(0, BigInt(metadata.timestamp), false);
83
- parts.push(new Uint8Array(timestampBuf));
84
- // providerCount: 1 byte
85
- parts.push(new Uint8Array([metadata.providers.length]));
86
- // each provider
87
- for (const p of metadata.providers) {
88
- const providerNameBytes = new TextEncoder().encode(p.provider);
89
- parts.push(new Uint8Array([providerNameBytes.length]));
90
- parts.push(providerNameBytes);
91
- pushServiceEntryCount(parts, p.services.length, hasWideServiceCounts);
92
- // each service: length-prefixed
93
- for (const service of p.services) {
94
- const serviceBytes = new TextEncoder().encode(service);
95
- parts.push(new Uint8Array([serviceBytes.length]));
96
- parts.push(serviceBytes);
97
- }
98
- // default input price: 4 bytes (float32)
99
- const inputPriceBuf = new ArrayBuffer(4);
100
- new DataView(inputPriceBuf).setFloat32(0, p.defaultPricing.inputUsdPerMillion, false);
101
- parts.push(new Uint8Array(inputPriceBuf));
102
- // default output price: 4 bytes (float32)
103
- const outputPriceBuf = new ArrayBuffer(4);
104
- new DataView(outputPriceBuf).setFloat32(0, p.defaultPricing.outputUsdPerMillion, false);
105
- parts.push(new Uint8Array(outputPriceBuf));
106
- // default cached input price: 4 bytes (float32) (v7+)
107
- const cachedInputPriceBuf = new ArrayBuffer(4);
108
- new DataView(cachedInputPriceBuf).setFloat32(0, p.defaultPricing.cachedInputUsdPerMillion ?? 0, false);
109
- parts.push(new Uint8Array(cachedInputPriceBuf));
110
- // servicePricing entries
111
- const servicePricingEntries = Object.entries(p.servicePricing ?? {}).sort(([a], [b]) => a.localeCompare(b));
112
- pushServiceEntryCount(parts, servicePricingEntries.length, hasWideServiceCounts);
113
- for (const [serviceName, pricing] of servicePricingEntries) {
114
- const serviceNameBytes = new TextEncoder().encode(serviceName);
115
- parts.push(new Uint8Array([serviceNameBytes.length]));
116
- parts.push(serviceNameBytes);
117
- const serviceInputBuf = new ArrayBuffer(4);
118
- new DataView(serviceInputBuf).setFloat32(0, pricing.inputUsdPerMillion, false);
119
- parts.push(new Uint8Array(serviceInputBuf));
120
- const serviceOutputBuf = new ArrayBuffer(4);
121
- new DataView(serviceOutputBuf).setFloat32(0, pricing.outputUsdPerMillion, false);
122
- parts.push(new Uint8Array(serviceOutputBuf));
123
- // service cached input price: 4 bytes (float32) (v7+)
124
- const serviceCachedInputBuf = new ArrayBuffer(4);
125
- new DataView(serviceCachedInputBuf).setFloat32(0, pricing.cachedInputUsdPerMillion ?? 0, false);
126
- parts.push(new Uint8Array(serviceCachedInputBuf));
127
- }
128
- if (hasServiceCategoryExtensions) {
129
- const serviceCategoryEntries = Object.entries(p.serviceCategories ?? {})
130
- .map(([serviceName, categories]) => {
131
- const normalizedCategories = Array.from(new Set(categories
132
- .map((category) => category.trim().toLowerCase())
133
- .filter((category) => category.length > 0))).sort();
134
- return [serviceName, normalizedCategories];
135
- })
136
- .filter(([, categories]) => categories.length > 0)
137
- .sort(([a], [b]) => a.localeCompare(b));
138
- pushServiceEntryCount(parts, serviceCategoryEntries.length, hasWideServiceCounts);
139
- for (const [serviceName, categories] of serviceCategoryEntries) {
140
- const serviceNameBytes = new TextEncoder().encode(serviceName);
141
- parts.push(new Uint8Array([serviceNameBytes.length]));
142
- parts.push(serviceNameBytes);
143
- parts.push(new Uint8Array([categories.length]));
144
- for (const category of categories) {
145
- const categoryBytes = new TextEncoder().encode(category);
146
- parts.push(new Uint8Array([categoryBytes.length]));
147
- parts.push(categoryBytes);
148
- }
149
- }
150
- }
151
- if (hasServiceApiProtocolExtensions) {
152
- const serviceApiProtocolEntries = Object.entries(p.serviceApiProtocols ?? {})
153
- .map(([serviceName, protocols]) => {
154
- const normalizedProtocols = Array.from(new Set(protocols
155
- .map((protocol) => protocol.trim().toLowerCase())
156
- .filter((protocol) => isKnownServiceApiProtocol(protocol)))).sort();
157
- return [serviceName, normalizedProtocols];
158
- })
159
- .filter(([, protocols]) => protocols.length > 0)
160
- .sort(([a], [b]) => a.localeCompare(b));
161
- pushServiceEntryCount(parts, serviceApiProtocolEntries.length, hasWideServiceCounts);
162
- for (const [serviceName, protocols] of serviceApiProtocolEntries) {
163
- const serviceNameBytes = new TextEncoder().encode(serviceName);
164
- parts.push(new Uint8Array([serviceNameBytes.length]));
165
- parts.push(serviceNameBytes);
166
- parts.push(new Uint8Array([protocols.length]));
167
- for (const protocol of protocols) {
168
- const protocolBytes = new TextEncoder().encode(protocol);
169
- parts.push(new Uint8Array([protocolBytes.length]));
170
- parts.push(protocolBytes);
171
- }
172
- }
173
- }
174
- if (metadata.version >= SERVICE_UNIT_BILLING_METADATA_VERSION) {
175
- encodeServiceUnitBillingModels(parts, p.serviceUnitBillingModels, hasWideServiceCounts);
176
- }
177
- if (metadata.version >= SERVICE_CAPABILITIES_METADATA_VERSION) {
178
- encodeServiceCapabilities(parts, p.serviceCapabilities, hasWideServiceCounts);
179
- }
180
- // maxConcurrency: 2 bytes (uint16)
181
- const maxConcBuf = new ArrayBuffer(2);
182
- new DataView(maxConcBuf).setUint16(0, p.maxConcurrency, false);
183
- parts.push(new Uint8Array(maxConcBuf));
184
- // currentLoad: 2 bytes (uint16)
185
- const loadBuf = new ArrayBuffer(2);
186
- new DataView(loadBuf).setUint16(0, p.currentLoad, false);
187
- parts.push(new Uint8Array(loadBuf));
188
- }
189
- if (hasServiceCategoryExtensions) {
190
- const displayName = metadata.displayName?.trim();
191
- if (displayName && displayName.length > 0) {
192
- const displayNameBytes = new TextEncoder().encode(displayName);
193
- parts.push(new Uint8Array([1]));
194
- parts.push(new Uint8Array([displayNameBytes.length]));
195
- parts.push(displayNameBytes);
196
- }
197
- else {
198
- parts.push(new Uint8Array([0]));
199
- }
200
- }
201
- if (metadata.version >= PUBLIC_ADDRESS_METADATA_VERSION) {
202
- const publicAddress = metadata.publicAddress?.trim();
203
- if (publicAddress && publicAddress.length > 0) {
204
- const publicAddressBytes = new TextEncoder().encode(publicAddress);
205
- parts.push(new Uint8Array([1]));
206
- parts.push(new Uint8Array([publicAddressBytes.length]));
207
- parts.push(publicAddressBytes);
208
- }
209
- else {
210
- parts.push(new Uint8Array([0]));
211
- }
212
- }
213
- // sellerContract (v8+) — flag + [sellerContract:20]
214
- // Buyers verify the peer→contract binding via `sellerContract.isOperator(peerAddress)`.
215
- if (metadata.version >= SELLER_CONTRACT_METADATA_VERSION) {
216
- const sc = metadata.sellerContract;
217
- if (sc) {
218
- parts.push(new Uint8Array([1]));
219
- parts.push(hexToBytes(sc)); // 20 bytes
220
- }
221
- else {
222
- parts.push(new Uint8Array([0]));
223
- }
224
- }
225
- if (metadata.version >= DOMAIN_VERIFICATION_METADATA_VERSION) {
226
- const claims = (metadata.verifications?.domains ?? [])
227
- .map((claim) => ({
228
- domain: claim.domain.trim().toLowerCase(),
229
- methods: claim.methods
230
- ? Array.from(new Set(claim.methods.map((method) => method.trim())))
231
- : undefined,
232
- }))
233
- .filter((claim) => claim.domain.length > 0)
234
- // Code-unit sort, not localeCompare: buyers verify signatures by
235
- // re-encoding decoded metadata, so claim order must not depend on the
236
- // verifier's locale.
237
- .sort((a, b) => (a.domain < b.domain ? -1 : a.domain > b.domain ? 1 : 0));
238
- if (claims.length > 255) {
239
- throw new Error(`Too many domain verification claims (${claims.length})`);
240
- }
241
- parts.push(new Uint8Array([claims.length]));
242
- for (const claim of claims) {
243
- const domainBytes = new TextEncoder().encode(claim.domain);
244
- if (domainBytes.length > 255) {
245
- throw new Error(`Domain verification claim too long (${domainBytes.length} bytes)`);
246
- }
247
- parts.push(new Uint8Array([domainBytes.length]));
248
- parts.push(domainBytes);
249
- const methods = claim.methods
250
- ? claim.methods
251
- .slice()
252
- .sort((a, b) => DOMAIN_VERIFICATION_METHOD_IDS[a] - DOMAIN_VERIFICATION_METHOD_IDS[b])
253
- : [];
254
- parts.push(new Uint8Array([methods.length]));
255
- for (const method of methods) {
256
- const methodId = DOMAIN_VERIFICATION_METHOD_IDS[method];
257
- if (methodId === undefined) {
258
- throw new Error(`Unsupported domain verification method "${method}"`);
259
- }
260
- parts.push(new Uint8Array([methodId]));
261
- }
262
- }
263
- const githubClaims = (metadata.verifications?.github ?? [])
264
- .map((claim) => ({
265
- username: claim.username.trim().toLowerCase(),
266
- repository: claim.repository ? claim.repository.trim().toLowerCase() : "",
267
- }))
268
- .filter((claim) => claim.username.length > 0)
269
- // Code-unit sort for the same locale-independence reason as domains.
270
- .sort((a, b) => (a.username < b.username ? -1 : a.username > b.username ? 1
271
- : a.repository < b.repository ? -1 : a.repository > b.repository ? 1 : 0));
272
- if (githubClaims.length > 255) {
273
- throw new Error(`Too many GitHub verification claims (${githubClaims.length})`);
274
- }
275
- parts.push(new Uint8Array([githubClaims.length]));
276
- for (const claim of githubClaims) {
277
- const usernameBytes = new TextEncoder().encode(claim.username);
278
- const repositoryBytes = new TextEncoder().encode(claim.repository);
279
- if (usernameBytes.length > 255 || repositoryBytes.length > 255) {
280
- throw new Error("GitHub verification claim too long");
281
- }
282
- parts.push(new Uint8Array([usernameBytes.length]));
283
- parts.push(usernameBytes);
284
- parts.push(new Uint8Array([repositoryBytes.length]));
285
- parts.push(repositoryBytes);
286
- }
287
- }
288
- // offerings
289
- const offerings = metadata.offerings ?? [];
290
- const offeringCountBuf = new ArrayBuffer(2);
291
- new DataView(offeringCountBuf).setUint16(0, offerings.length, false);
292
- parts.push(new Uint8Array(offeringCountBuf));
293
- const PRICING_UNIT_MAP = { token: 0, request: 1, minute: 2, task: 3 };
294
- for (const o of offerings) {
295
- const capBytes = new TextEncoder().encode(o.capability);
296
- parts.push(new Uint8Array([capBytes.length]));
297
- parts.push(capBytes);
298
- const nameBytes = new TextEncoder().encode(o.name);
299
- parts.push(new Uint8Array([nameBytes.length]));
300
- parts.push(nameBytes);
301
- const descBytes = new TextEncoder().encode(o.description);
302
- const descLenBuf = new ArrayBuffer(2);
303
- new DataView(descLenBuf).setUint16(0, descBytes.length, false);
304
- parts.push(new Uint8Array(descLenBuf));
305
- parts.push(descBytes);
306
- parts.push(new Uint8Array([PRICING_UNIT_MAP[o.pricing.unit] ?? 0]));
307
- const priceBuf = new ArrayBuffer(4);
308
- new DataView(priceBuf).setFloat32(0, o.pricing.pricePerUnit, false);
309
- parts.push(new Uint8Array(priceBuf));
310
- const offeringServices = o.services ?? [];
311
- parts.push(new Uint8Array([offeringServices.length]));
312
- for (const service of offeringServices) {
313
- const serviceBytes = new TextEncoder().encode(service);
314
- parts.push(new Uint8Array([serviceBytes.length]));
315
- parts.push(serviceBytes);
316
- }
317
- }
318
- // On-chain stats: 1 flag byte + 10 data bytes (1 reserved + 4 channelCount + 4 ghostCount + 1 reserved)
319
- if (metadata.onChainChannelCount !== undefined) {
320
- parts.push(new Uint8Array([1])); // flag: present
321
- const repBuf = new ArrayBuffer(10);
322
- const repView = new DataView(repBuf);
323
- repView.setUint8(0, Math.min(255, metadata.onChainChannelCount)); // legacy reputation byte — channelCount capped to u8
324
- repView.setUint32(1, metadata.onChainChannelCount, false);
325
- repView.setUint32(5, metadata.onChainGhostCount ?? 0, false);
326
- repView.setUint8(9, 0); // reserved
327
- parts.push(new Uint8Array(repBuf));
328
- }
329
- else {
330
- parts.push(new Uint8Array([0])); // flag: absent
331
- }
332
- if (metadata.version >= PEER_CAPABILITIES_METADATA_VERSION) {
333
- const capabilities = Array.from(new Set((metadata.capabilities ?? [])
334
- .map((capability) => capability.trim().toLowerCase())
335
- .filter((capability) => capability.length > 0))).sort();
336
- parts.push(new Uint8Array([capabilities.length]));
337
- for (const capability of capabilities) {
338
- const capabilityBytes = new TextEncoder().encode(capability);
339
- parts.push(new Uint8Array([capabilityBytes.length]));
340
- parts.push(capabilityBytes);
341
- }
342
- }
343
- // Combine all parts
344
- const totalLength = parts.reduce((sum, p) => sum + p.length, 0);
345
- const result = new Uint8Array(totalLength);
346
- let offset = 0;
347
- for (const part of parts) {
348
- result.set(part, offset);
349
- offset += part.length;
350
- }
351
- return result;
352
- }
353
- function encodeServiceUnitBillingModels(parts, serviceUnitBillingModels, hasWideServiceCounts) {
354
- const entries = [];
355
- for (const [serviceName, protocolModels] of Object.entries(serviceUnitBillingModels ?? {})) {
356
- for (const protocol of WELL_KNOWN_SERVICE_API_PROTOCOLS) {
357
- const model = protocolModels?.[protocol];
358
- if (model)
359
- entries.push([serviceName, protocol, model]);
360
- }
361
- }
362
- entries.sort(([serviceA, protocolA], [serviceB, protocolB]) => serviceA === serviceB
363
- ? WELL_KNOWN_SERVICE_API_PROTOCOLS.indexOf(protocolA) - WELL_KNOWN_SERVICE_API_PROTOCOLS.indexOf(protocolB)
364
- : serviceA.localeCompare(serviceB));
365
- pushServiceEntryCount(parts, entries.length, hasWideServiceCounts);
366
- for (const [serviceName, protocol, model] of entries) {
367
- pushUtf8(parts, serviceName);
368
- parts.push(new Uint8Array([WELL_KNOWN_SERVICE_API_PROTOCOLS.indexOf(protocol)]));
369
- parts.push(new Uint8Array([model.version]));
370
- parts.push(new Uint8Array([model.components.length]));
371
- for (const component of model.components) {
372
- parts.push(new Uint8Array([UNIT_BILLING_UNIT_IDS.get(component.unit) ?? 255]));
373
- const priceBuf = new ArrayBuffer(4);
374
- new DataView(priceBuf).setFloat32(0, component.priceUsd, false);
375
- parts.push(new Uint8Array(priceBuf));
376
- const matchEntries = Object.entries(component.match ?? {})
377
- .filter((entry) => UNIT_BILLING_MATCH_KEY_IDS.has(entry[0]))
378
- .sort(([a], [b]) => (UNIT_BILLING_MATCH_KEY_IDS.get(a) ?? 0) - (UNIT_BILLING_MATCH_KEY_IDS.get(b) ?? 0));
379
- parts.push(new Uint8Array([matchEntries.length]));
380
- for (const [key, value] of matchEntries) {
381
- parts.push(new Uint8Array([UNIT_BILLING_MATCH_KEY_IDS.get(key) ?? 255]));
382
- pushUtf8(parts, value);
383
- }
384
- }
385
- }
386
- }
387
- // Presence bits for the per-service capability entry. A set bit means the
388
- // field was announced (booleans distinguish "known false" from "unknown").
389
- const CAP_HAS_CONTEXT_WINDOW = 1 << 0;
390
- const CAP_HAS_MAX_OUTPUT_TOKENS = 1 << 1;
391
- const CAP_HAS_INPUTS = 1 << 2;
392
- const CAP_HAS_REASONING = 1 << 3;
393
- const CAP_HAS_TOOL_USE = 1 << 4;
394
- const CAP_HAS_STRUCTURED_OUTPUT = 1 << 5;
395
- const CAP_HAS_OUTPUTS = 1 << 6;
396
- const CAP_HAS_SUPPORTED_PARAMETERS = 1 << 7;
397
- const CAP_PRESENCE_MASK = CAP_HAS_CONTEXT_WINDOW | CAP_HAS_MAX_OUTPUT_TOKENS | CAP_HAS_INPUTS
398
- | CAP_HAS_REASONING | CAP_HAS_TOOL_USE | CAP_HAS_STRUCTURED_OUTPUT
399
- | CAP_HAS_OUTPUTS | CAP_HAS_SUPPORTED_PARAMETERS;
400
- const CAP_VAL_REASONING = 1 << 0;
401
- const CAP_VAL_TOOL_USE = 1 << 1;
402
- const CAP_VAL_STRUCTURED_OUTPUT = 1 << 2;
403
- const CAP_VAL_VIDEO_OPTIONS = 1 << 3;
404
- const CAP_VALUE_MASK = CAP_VAL_REASONING | CAP_VAL_TOOL_USE | CAP_VAL_STRUCTURED_OUTPUT
405
- | CAP_VAL_VIDEO_OPTIONS;
406
- const CAP_MODALITY_MASK = (1 << SERVICE_CAPABILITY_MODALITIES.length) - 1;
407
- const VIDEO_HAS_DURATIONS = 1 << 0;
408
- const VIDEO_HAS_RESOLUTIONS = 1 << 1;
409
- const VIDEO_HAS_ASPECT_RATIOS = 1 << 2;
410
- const VIDEO_HAS_INPUTS = 1 << 3;
411
- const VIDEO_HAS_REQUIRED_INPUTS = 1 << 4;
412
- const VIDEO_HAS_AUDIO = 1 << 5;
413
- const VIDEO_AUDIO = 1 << 6;
414
- const VIDEO_OPTION_MASK = (1 << 7) - 1;
415
- const VIDEO_INPUT_MASK = (1 << VIDEO_INPUT_KINDS.length) - 1;
416
- function encodeModalityBits(modalities) {
417
- let bits = 0;
418
- for (const modality of modalities) {
419
- const id = SERVICE_CAPABILITY_MODALITIES.indexOf(modality);
420
- if (id >= 0)
421
- bits |= 1 << id;
422
- }
423
- return bits;
424
- }
425
- function decodeModalityBits(bits, label) {
426
- if (bits & ~CAP_MODALITY_MASK) {
427
- throw new Error(`Unknown service capability ${label} bits 0x${bits.toString(16)}`);
428
- }
429
- const modalities = [];
430
- for (let id = 0; id < SERVICE_CAPABILITY_MODALITIES.length; id += 1) {
431
- if (bits & (1 << id))
432
- modalities.push(SERVICE_CAPABILITY_MODALITIES[id]);
433
- }
434
- return modalities;
435
- }
436
- function encodeVideoInputs(inputs) {
437
- return inputs.reduce((bits, input) => bits | (1 << VIDEO_INPUT_KINDS.indexOf(input)), 0);
438
- }
439
- function decodeVideoInputs(bits) {
440
- if (bits & ~VIDEO_INPUT_MASK)
441
- throw new Error(`Unknown video input bits 0x${bits.toString(16)}`);
442
- return VIDEO_INPUT_KINDS.filter((_, id) => bits & (1 << id));
443
- }
444
- function encodeVideoOptions(parts, video) {
445
- let flags = 0;
446
- if (video.durationsSeconds)
447
- flags |= VIDEO_HAS_DURATIONS;
448
- if (video.resolutions)
449
- flags |= VIDEO_HAS_RESOLUTIONS;
450
- if (video.aspectRatios)
451
- flags |= VIDEO_HAS_ASPECT_RATIOS;
452
- if (video.inputs)
453
- flags |= VIDEO_HAS_INPUTS;
454
- if (video.requiredInputs)
455
- flags |= VIDEO_HAS_REQUIRED_INPUTS;
456
- if (video.audio !== undefined)
457
- flags |= VIDEO_HAS_AUDIO | (video.audio ? VIDEO_AUDIO : 0);
458
- parts.push(new Uint8Array([flags]));
459
- if (video.durationsSeconds) {
460
- parts.push(new Uint8Array([video.durationsSeconds.length]));
461
- for (const duration of video.durationsSeconds)
462
- parts.push(new Uint8Array([duration >> 8, duration & 0xff]));
463
- }
464
- for (const values of [video.resolutions, video.aspectRatios]) {
465
- if (!values)
466
- continue;
467
- parts.push(new Uint8Array([values.length]));
468
- for (const value of values)
469
- pushUtf8(parts, value);
470
- }
471
- if (video.inputs)
472
- parts.push(new Uint8Array([encodeVideoInputs(video.inputs)]));
473
- if (video.requiredInputs)
474
- parts.push(new Uint8Array([encodeVideoInputs(video.requiredInputs)]));
475
- }
476
- function decodeVideoOptions(data, offset, checkBounds) {
477
- checkBounds(offset, 1, data.length);
478
- const flags = data[offset++];
479
- if (flags & ~VIDEO_OPTION_MASK || (flags & VIDEO_AUDIO && !(flags & VIDEO_HAS_AUDIO)))
480
- throw new Error(`Unknown video option bits 0x${flags.toString(16)}`);
481
- const video = {};
482
- if (flags & VIDEO_HAS_DURATIONS) {
483
- checkBounds(offset, 1, data.length);
484
- const count = data[offset++];
485
- checkBounds(offset, count * 2, data.length);
486
- video.durationsSeconds = Array.from({ length: count }, (_, index) => (data[offset + index * 2] << 8) | data[offset + index * 2 + 1]);
487
- offset += count * 2;
488
- }
489
- for (const [flag, field] of [[VIDEO_HAS_RESOLUTIONS, "resolutions"], [VIDEO_HAS_ASPECT_RATIOS, "aspectRatios"]]) {
490
- if (!(flags & flag))
491
- continue;
492
- checkBounds(offset, 1, data.length);
493
- const count = data[offset++];
494
- const values = [];
495
- for (let index = 0; index < count; index += 1) {
496
- const [value, nextOffset] = readUtf8(data, offset, checkBounds);
497
- values.push(value);
498
- offset = nextOffset;
499
- }
500
- video[field] = values;
501
- }
502
- for (const [flag, field] of [[VIDEO_HAS_INPUTS, "inputs"], [VIDEO_HAS_REQUIRED_INPUTS, "requiredInputs"]]) {
503
- if (!(flags & flag))
504
- continue;
505
- checkBounds(offset, 1, data.length);
506
- video[field] = decodeVideoInputs(data[offset++]);
507
- }
508
- if (flags & VIDEO_HAS_AUDIO)
509
- video.audio = (flags & VIDEO_AUDIO) !== 0;
510
- return [video, offset];
511
- }
512
- function encodeServiceCapabilities(parts, serviceCapabilities, hasWideServiceCounts) {
513
- // Code-unit sort, not localeCompare: buyers verify signatures by re-encoding
514
- // decoded metadata, so entry order must not depend on the verifier's locale.
515
- const entries = Object.entries(serviceCapabilities ?? {})
516
- .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
517
- pushServiceEntryCount(parts, entries.length, hasWideServiceCounts);
518
- for (const [serviceName, caps] of entries) {
519
- pushUtf8(parts, serviceName);
520
- let presence = 0;
521
- if (caps.contextWindow !== undefined)
522
- presence |= CAP_HAS_CONTEXT_WINDOW;
523
- if (caps.maxOutputTokens !== undefined)
524
- presence |= CAP_HAS_MAX_OUTPUT_TOKENS;
525
- if (caps.inputs !== undefined)
526
- presence |= CAP_HAS_INPUTS;
527
- if (caps.outputs !== undefined)
528
- presence |= CAP_HAS_OUTPUTS;
529
- if (caps.reasoning !== undefined)
530
- presence |= CAP_HAS_REASONING;
531
- if (caps.toolUse !== undefined)
532
- presence |= CAP_HAS_TOOL_USE;
533
- if (caps.structuredOutput !== undefined)
534
- presence |= CAP_HAS_STRUCTURED_OUTPUT;
535
- if (caps.supportedParameters !== undefined)
536
- presence |= CAP_HAS_SUPPORTED_PARAMETERS;
537
- parts.push(new Uint8Array([presence]));
538
- if (caps.contextWindow !== undefined) {
539
- const buf = new ArrayBuffer(4);
540
- new DataView(buf).setUint32(0, caps.contextWindow, false);
541
- parts.push(new Uint8Array(buf));
542
- }
543
- if (caps.maxOutputTokens !== undefined) {
544
- const buf = new ArrayBuffer(4);
545
- new DataView(buf).setUint32(0, caps.maxOutputTokens, false);
546
- parts.push(new Uint8Array(buf));
547
- }
548
- if (caps.inputs !== undefined) {
549
- parts.push(new Uint8Array([encodeModalityBits(caps.inputs)]));
550
- }
551
- if (caps.outputs !== undefined) {
552
- parts.push(new Uint8Array([encodeModalityBits(caps.outputs)]));
553
- }
554
- let boolBits = 0;
555
- if (caps.reasoning === true)
556
- boolBits |= CAP_VAL_REASONING;
557
- if (caps.toolUse === true)
558
- boolBits |= CAP_VAL_TOOL_USE;
559
- if (caps.structuredOutput === true)
560
- boolBits |= CAP_VAL_STRUCTURED_OUTPUT;
561
- if (caps.video !== undefined)
562
- boolBits |= CAP_VAL_VIDEO_OPTIONS;
563
- parts.push(new Uint8Array([boolBits]));
564
- if (caps.supportedParameters !== undefined) {
565
- // Code-unit sort for the same reason as the entry sort above: buyers
566
- // verify signatures by re-encoding decoded metadata.
567
- const parameters = [...caps.supportedParameters].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
568
- if (parameters.length > 255) {
569
- throw new Error(`Too many supported parameters (${parameters.length})`);
570
- }
571
- parts.push(new Uint8Array([parameters.length]));
572
- for (const parameter of parameters) {
573
- pushUtf8(parts, parameter);
574
- }
575
- }
576
- if (caps.video !== undefined)
577
- encodeVideoOptions(parts, caps.video);
578
- }
579
- }
580
- function decodeServiceCapabilities(data, getOffset, setOffset, checkBounds, hasWideServiceCounts) {
581
- let offset = getOffset();
582
- const [entryCount, nextOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
583
- offset = nextOffset;
584
- const serviceCapabilities = {};
585
- for (let i = 0; i < entryCount; i += 1) {
586
- const [serviceName, serviceOffset] = readUtf8(data, offset, checkBounds);
587
- offset = serviceOffset;
588
- checkBounds(offset, 1, data.length);
589
- const presence = data[offset];
590
- offset += 1;
591
- if (presence & ~CAP_PRESENCE_MASK) {
592
- // Unknown bits would decode into a struct that re-encodes to different
593
- // bytes and fails signature verification anyway — reject explicitly so
594
- // additive extensions are forced through a metadata version bump.
595
- throw new Error(`Unknown service capability presence bits 0x${presence.toString(16)}`);
596
- }
597
- const caps = {};
598
- if (presence & CAP_HAS_CONTEXT_WINDOW) {
599
- checkBounds(offset, 4, data.length);
600
- caps.contextWindow = new DataView(data.buffer, data.byteOffset + offset, 4).getUint32(0, false);
601
- offset += 4;
602
- }
603
- if (presence & CAP_HAS_MAX_OUTPUT_TOKENS) {
604
- checkBounds(offset, 4, data.length);
605
- caps.maxOutputTokens = new DataView(data.buffer, data.byteOffset + offset, 4).getUint32(0, false);
606
- offset += 4;
607
- }
608
- if (presence & CAP_HAS_INPUTS) {
609
- checkBounds(offset, 1, data.length);
610
- caps.inputs = decodeModalityBits(data[offset], "input");
611
- offset += 1;
612
- }
613
- if (presence & CAP_HAS_OUTPUTS) {
614
- checkBounds(offset, 1, data.length);
615
- caps.outputs = decodeModalityBits(data[offset], "output");
616
- offset += 1;
617
- }
618
- checkBounds(offset, 1, data.length);
619
- const boolBits = data[offset];
620
- offset += 1;
621
- if (boolBits & ~CAP_VALUE_MASK) {
622
- throw new Error(`Unknown service capability value bits 0x${boolBits.toString(16)}`);
623
- }
624
- if (presence & CAP_HAS_REASONING)
625
- caps.reasoning = (boolBits & CAP_VAL_REASONING) !== 0;
626
- if (presence & CAP_HAS_TOOL_USE)
627
- caps.toolUse = (boolBits & CAP_VAL_TOOL_USE) !== 0;
628
- if (presence & CAP_HAS_STRUCTURED_OUTPUT)
629
- caps.structuredOutput = (boolBits & CAP_VAL_STRUCTURED_OUTPUT) !== 0;
630
- if (presence & CAP_HAS_SUPPORTED_PARAMETERS) {
631
- checkBounds(offset, 1, data.length);
632
- const parameterCount = data[offset];
633
- offset += 1;
634
- const parameters = [];
635
- for (let p = 0; p < parameterCount; p += 1) {
636
- const [parameter, parameterOffset] = readUtf8(data, offset, checkBounds);
637
- offset = parameterOffset;
638
- parameters.push(parameter);
639
- }
640
- caps.supportedParameters = parameters;
641
- }
642
- if (boolBits & CAP_VAL_VIDEO_OPTIONS)
643
- [caps.video, offset] = decodeVideoOptions(data, offset, checkBounds);
644
- serviceCapabilities[serviceName] = caps;
645
- }
646
- setOffset(offset);
647
- return Object.keys(serviceCapabilities).length > 0 ? serviceCapabilities : undefined;
648
- }
649
- function pushUtf8(parts, value) {
650
- const bytes = new TextEncoder().encode(value);
651
- if (bytes.length > 255) {
652
- throw new Error(`Metadata string too long (${bytes.length} bytes)`);
653
- }
654
- parts.push(new Uint8Array([bytes.length]));
655
- parts.push(bytes);
656
- }
657
- function pushServiceEntryCount(parts, count, hasWideServiceCounts) {
658
- if (hasWideServiceCounts) {
659
- if (count > 0xffff)
660
- throw new Error(`Service entry count ${count} exceeds uint16`);
661
- const countBuffer = new ArrayBuffer(2);
662
- new DataView(countBuffer).setUint16(0, count, false);
663
- parts.push(new Uint8Array(countBuffer));
664
- return;
665
- }
666
- if (count > 0xff)
667
- throw new Error(`Service entry count ${count} requires metadata v${WIDE_SERVICE_COUNTS_METADATA_VERSION}`);
668
- parts.push(new Uint8Array([count]));
669
- }
670
- function readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts) {
671
- const width = hasWideServiceCounts ? 2 : 1;
672
- checkBounds(offset, width, data.length);
673
- if (!hasWideServiceCounts)
674
- return [data[offset], offset + 1];
675
- return [new DataView(data.buffer, data.byteOffset + offset, 2).getUint16(0, false), offset + 2];
676
- }
677
- function decodeServiceUnitBillingModels(data, getOffset, setOffset, checkBounds, hasWideServiceCounts) {
678
- let offset = getOffset();
679
- const [entryCount, nextOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
680
- offset = nextOffset;
681
- const serviceUnitBillingModels = {};
682
- for (let i = 0; i < entryCount; i += 1) {
683
- const [serviceName, serviceOffset] = readUtf8(data, offset, checkBounds);
684
- offset = serviceOffset;
685
- checkBounds(offset, 1, data.length);
686
- const protocol = WELL_KNOWN_SERVICE_API_PROTOCOLS[data[offset]];
687
- offset += 1;
688
- if (!protocol) {
689
- throw new Error("Unsupported service unit billing protocol id");
690
- }
691
- checkBounds(offset, 2, data.length);
692
- const version = data[offset];
693
- offset += 1;
694
- if (version !== 1) {
695
- throw new Error(`Unsupported service unit billing model version ${version}`);
696
- }
697
- const componentCount = data[offset];
698
- offset += 1;
699
- const components = [];
700
- for (let j = 0; j < componentCount; j += 1) {
701
- checkBounds(offset, 6, data.length);
702
- const unit = UNIT_BILLING_UNITS_BY_ID[data[offset]];
703
- offset += 1;
704
- if (!unit) {
705
- throw new Error("Unsupported service unit billing component unit");
706
- }
707
- const priceUsd = new DataView(data.buffer, data.byteOffset + offset, 4).getFloat32(0, false);
708
- offset += 4;
709
- const matchCount = data[offset];
710
- offset += 1;
711
- const match = {};
712
- for (let k = 0; k < matchCount; k += 1) {
713
- checkBounds(offset, 1, data.length);
714
- const key = UNIT_BILLING_MATCH_KEYS_BY_ID[data[offset]];
715
- offset += 1;
716
- if (!key) {
717
- throw new Error("Unsupported service unit billing match key");
718
- }
719
- const [value, valueOffset] = readUtf8(data, offset, checkBounds);
720
- offset = valueOffset;
721
- match[key] = value;
722
- }
723
- const base = { unit, priceUsd, ...(Object.keys(match).length > 0 ? { match } : {}) };
724
- components.push(base);
725
- }
726
- serviceUnitBillingModels[serviceName] = {
727
- ...(serviceUnitBillingModels[serviceName] ?? {}),
728
- [protocol]: { version: 1, components },
729
- };
730
- }
731
- setOffset(offset);
732
- return Object.keys(serviceUnitBillingModels).length > 0 ? serviceUnitBillingModels : undefined;
733
- }
734
- function readUtf8(data, offset, checkBounds) {
735
- checkBounds(offset, 1, data.length);
736
- const length = data[offset];
737
- const valueOffset = offset + 1;
738
- checkBounds(valueOffset, length, data.length);
739
- return [new TextDecoder().decode(data.slice(valueOffset, valueOffset + length)), valueOffset + length];
740
- }
741
- /**
742
- * Decode binary metadata back into PeerMetadata.
743
- */
744
- export function decodeMetadata(data) {
745
- function checkBounds(offset, needed, total) {
746
- if (offset + needed > total)
747
- throw new Error('Truncated metadata buffer');
748
- }
749
- let offset = 0;
750
- // version: 1 byte
751
- checkBounds(offset, 1, data.length);
752
- const version = data[offset];
753
- if (version < 7) {
754
- throw new Error(`Unsupported metadata version ${version}: pre-v7 format is no longer supported`);
755
- }
756
- const hasServiceCategoryExtensions = version >= SERVICE_CATEGORIES_METADATA_VERSION;
757
- const hasServiceApiProtocolExtensions = version >= SERVICE_API_PROTOCOLS_METADATA_VERSION;
758
- const hasPublicAddressExtension = version >= PUBLIC_ADDRESS_METADATA_VERSION;
759
- const hasWideServiceCounts = version >= WIDE_SERVICE_COUNTS_METADATA_VERSION;
760
- offset += 1;
761
- // peerId: 20 bytes (EVM address)
762
- checkBounds(offset, 20, data.length);
763
- const peerIdBytes = data.slice(offset, offset + 20);
764
- const peerId = bytesToHex(peerIdBytes);
765
- offset += 20;
766
- // region: length-prefixed
767
- checkBounds(offset, 1, data.length);
768
- const regionLen = data[offset];
769
- offset += 1;
770
- checkBounds(offset, regionLen, data.length);
771
- const region = new TextDecoder().decode(data.slice(offset, offset + regionLen));
772
- offset += regionLen;
773
- // timestamp: 8 bytes BigUint64
774
- checkBounds(offset, 8, data.length);
775
- const timestampView = new DataView(data.buffer, data.byteOffset + offset, 8);
776
- const timestamp = Number(timestampView.getBigUint64(0, false));
777
- offset += 8;
778
- // providerCount: 1 byte
779
- checkBounds(offset, 1, data.length);
780
- const providerCount = data[offset];
781
- offset += 1;
782
- const providers = [];
783
- for (let i = 0; i < providerCount; i++) {
784
- // provider name: length-prefixed
785
- checkBounds(offset, 1, data.length);
786
- const providerLen = data[offset];
787
- offset += 1;
788
- checkBounds(offset, providerLen, data.length);
789
- const provider = new TextDecoder().decode(data.slice(offset, offset + providerLen));
790
- offset += providerLen;
791
- const [serviceCount, serviceCountOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
792
- offset = serviceCountOffset;
793
- const services = [];
794
- for (let j = 0; j < serviceCount; j++) {
795
- checkBounds(offset, 1, data.length);
796
- const serviceLen = data[offset];
797
- offset += 1;
798
- checkBounds(offset, serviceLen, data.length);
799
- const service = new TextDecoder().decode(data.slice(offset, offset + serviceLen));
800
- offset += serviceLen;
801
- services.push(service);
802
- }
803
- // default input price: 4 bytes float32
804
- checkBounds(offset, 4, data.length);
805
- const inputPriceView = new DataView(data.buffer, data.byteOffset + offset, 4);
806
- const defaultInputUsdPerMillion = inputPriceView.getFloat32(0, false);
807
- offset += 4;
808
- // default output price: 4 bytes float32
809
- checkBounds(offset, 4, data.length);
810
- const outputPriceView = new DataView(data.buffer, data.byteOffset + offset, 4);
811
- const defaultOutputUsdPerMillion = outputPriceView.getFloat32(0, false);
812
- offset += 4;
813
- // default cached input price: 4 bytes float32 (v7+)
814
- checkBounds(offset, 4, data.length);
815
- const cachedInputPriceView = new DataView(data.buffer, data.byteOffset + offset, 4);
816
- const defaultCachedInputUsdPerMillion = cachedInputPriceView.getFloat32(0, false);
817
- offset += 4;
818
- // servicePricing entries
819
- const [servicePricingCount, servicePricingOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
820
- offset = servicePricingOffset;
821
- const servicePricing = {};
822
- for (let j = 0; j < servicePricingCount; j++) {
823
- checkBounds(offset, 1, data.length);
824
- const pricedServiceLen = data[offset];
825
- offset += 1;
826
- checkBounds(offset, pricedServiceLen, data.length);
827
- const pricedServiceName = new TextDecoder().decode(data.slice(offset, offset + pricedServiceLen));
828
- offset += pricedServiceLen;
829
- checkBounds(offset, 4, data.length);
830
- const pricedInputView = new DataView(data.buffer, data.byteOffset + offset, 4);
831
- const inputUsdPerMillion = pricedInputView.getFloat32(0, false);
832
- offset += 4;
833
- checkBounds(offset, 4, data.length);
834
- const pricedOutputView = new DataView(data.buffer, data.byteOffset + offset, 4);
835
- const outputUsdPerMillion = pricedOutputView.getFloat32(0, false);
836
- offset += 4;
837
- // service cached input price: 4 bytes float32 (v7+)
838
- checkBounds(offset, 4, data.length);
839
- const pricedCachedInputView = new DataView(data.buffer, data.byteOffset + offset, 4);
840
- const cachedInputUsdPerMillion = pricedCachedInputView.getFloat32(0, false);
841
- offset += 4;
842
- servicePricing[pricedServiceName] = {
843
- inputUsdPerMillion,
844
- outputUsdPerMillion,
845
- ...(cachedInputUsdPerMillion !== 0 ? { cachedInputUsdPerMillion } : {}),
846
- };
847
- }
848
- let serviceCategories;
849
- if (hasServiceCategoryExtensions) {
850
- const [serviceCategoryCount, serviceCategoryOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
851
- offset = serviceCategoryOffset;
852
- if (serviceCategoryCount > 0) {
853
- serviceCategories = {};
854
- for (let j = 0; j < serviceCategoryCount; j++) {
855
- checkBounds(offset, 1, data.length);
856
- const categorizedServiceLen = data[offset];
857
- offset += 1;
858
- checkBounds(offset, categorizedServiceLen, data.length);
859
- const categorizedServiceName = new TextDecoder().decode(data.slice(offset, offset + categorizedServiceLen));
860
- offset += categorizedServiceLen;
861
- checkBounds(offset, 1, data.length);
862
- const categoryCount = data[offset];
863
- offset += 1;
864
- const categories = [];
865
- for (let k = 0; k < categoryCount; k++) {
866
- checkBounds(offset, 1, data.length);
867
- const categoryLen = data[offset];
868
- offset += 1;
869
- checkBounds(offset, categoryLen, data.length);
870
- const category = new TextDecoder().decode(data.slice(offset, offset + categoryLen));
871
- offset += categoryLen;
872
- categories.push(category);
873
- }
874
- serviceCategories[categorizedServiceName] = categories;
875
- }
876
- }
877
- }
878
- let serviceApiProtocols;
879
- if (hasServiceApiProtocolExtensions) {
880
- const [serviceApiProtocolCount, serviceApiProtocolOffset] = readServiceEntryCount(data, offset, checkBounds, hasWideServiceCounts);
881
- offset = serviceApiProtocolOffset;
882
- if (serviceApiProtocolCount > 0) {
883
- serviceApiProtocols = {};
884
- for (let j = 0; j < serviceApiProtocolCount; j++) {
885
- checkBounds(offset, 1, data.length);
886
- const protocolServiceLen = data[offset];
887
- offset += 1;
888
- checkBounds(offset, protocolServiceLen, data.length);
889
- const protocolServiceName = new TextDecoder().decode(data.slice(offset, offset + protocolServiceLen));
890
- offset += protocolServiceLen;
891
- checkBounds(offset, 1, data.length);
892
- const protocolCount = data[offset];
893
- offset += 1;
894
- const protocols = [];
895
- for (let k = 0; k < protocolCount; k++) {
896
- checkBounds(offset, 1, data.length);
897
- const protocolLen = data[offset];
898
- offset += 1;
899
- checkBounds(offset, protocolLen, data.length);
900
- const protocol = new TextDecoder().decode(data.slice(offset, offset + protocolLen));
901
- offset += protocolLen;
902
- protocols.push(protocol);
903
- }
904
- serviceApiProtocols[protocolServiceName] = protocols;
905
- }
906
- }
907
- }
908
- const serviceUnitBillingModels = version >= SERVICE_UNIT_BILLING_METADATA_VERSION
909
- ? decodeServiceUnitBillingModels(data, () => offset, (next) => { offset = next; }, checkBounds, hasWideServiceCounts)
910
- : undefined;
911
- const serviceCapabilities = version >= SERVICE_CAPABILITIES_METADATA_VERSION
912
- ? decodeServiceCapabilities(data, () => offset, (next) => { offset = next; }, checkBounds, hasWideServiceCounts)
913
- : undefined;
914
- // maxConcurrency: 2 bytes uint16
915
- checkBounds(offset, 2, data.length);
916
- const maxConcView = new DataView(data.buffer, data.byteOffset + offset, 2);
917
- const maxConcurrency = maxConcView.getUint16(0, false);
918
- offset += 2;
919
- // currentLoad: 2 bytes uint16
920
- checkBounds(offset, 2, data.length);
921
- const loadView = new DataView(data.buffer, data.byteOffset + offset, 2);
922
- const currentLoad = loadView.getUint16(0, false);
923
- offset += 2;
924
- providers.push({
925
- provider,
926
- services,
927
- defaultPricing: {
928
- inputUsdPerMillion: defaultInputUsdPerMillion,
929
- outputUsdPerMillion: defaultOutputUsdPerMillion,
930
- ...(defaultCachedInputUsdPerMillion !== 0 ? { cachedInputUsdPerMillion: defaultCachedInputUsdPerMillion } : {}),
931
- },
932
- ...(servicePricingCount > 0 ? { servicePricing } : {}),
933
- ...(serviceCategories && Object.keys(serviceCategories).length > 0 ? { serviceCategories } : {}),
934
- ...(serviceApiProtocols && Object.keys(serviceApiProtocols).length > 0 ? { serviceApiProtocols } : {}),
935
- ...(serviceUnitBillingModels && Object.keys(serviceUnitBillingModels).length > 0 ? { serviceUnitBillingModels } : {}),
936
- ...(serviceCapabilities && Object.keys(serviceCapabilities).length > 0 ? { serviceCapabilities } : {}),
937
- maxConcurrency,
938
- currentLoad,
939
- });
940
- }
941
- let displayName;
942
- if (hasServiceCategoryExtensions) {
943
- checkBounds(offset, 1, data.length - 65);
944
- const displayNameFlag = data[offset];
945
- offset += 1;
946
- if (displayNameFlag === 1) {
947
- checkBounds(offset, 1, data.length - 65);
948
- const displayNameLen = data[offset];
949
- offset += 1;
950
- checkBounds(offset, displayNameLen, data.length - 65);
951
- displayName = new TextDecoder().decode(data.slice(offset, offset + displayNameLen));
952
- offset += displayNameLen;
953
- }
954
- }
955
- let publicAddress;
956
- if (hasPublicAddressExtension) {
957
- checkBounds(offset, 1, data.length - 65);
958
- const publicAddressFlag = data[offset];
959
- offset += 1;
960
- if (publicAddressFlag === 1) {
961
- checkBounds(offset, 1, data.length - 65);
962
- const publicAddressLen = data[offset];
963
- offset += 1;
964
- checkBounds(offset, publicAddressLen, data.length - 65);
965
- publicAddress = new TextDecoder().decode(data.slice(offset, offset + publicAddressLen));
966
- offset += publicAddressLen;
967
- }
968
- }
969
- let sellerContract;
970
- if (version >= SELLER_CONTRACT_METADATA_VERSION) {
971
- checkBounds(offset, 1, data.length - 65);
972
- const sellerContractFlag = data[offset];
973
- offset += 1;
974
- if (sellerContractFlag === 1) {
975
- checkBounds(offset, 20, data.length - 65);
976
- sellerContract = bytesToHex(data.slice(offset, offset + 20));
977
- offset += 20;
978
- }
979
- }
980
- let domainVerifications;
981
- if (version >= DOMAIN_VERIFICATION_METADATA_VERSION) {
982
- checkBounds(offset, 1, data.length - 65);
983
- const domainVerificationCount = data[offset];
984
- offset += 1;
985
- if (domainVerificationCount > 0) {
986
- domainVerifications = [];
987
- for (let i = 0; i < domainVerificationCount; i += 1) {
988
- checkBounds(offset, 1, data.length - 65);
989
- const domainLen = data[offset];
990
- offset += 1;
991
- checkBounds(offset, domainLen, data.length - 65);
992
- const domain = new TextDecoder().decode(data.slice(offset, offset + domainLen));
993
- offset += domainLen;
994
- checkBounds(offset, 1, data.length - 65);
995
- const methodCount = data[offset];
996
- offset += 1;
997
- const methods = [];
998
- for (let j = 0; j < methodCount; j += 1) {
999
- checkBounds(offset, 1, data.length - 65);
1000
- const method = DOMAIN_VERIFICATION_METHODS_BY_ID[data[offset]];
1001
- offset += 1;
1002
- if (method === undefined) {
1003
- throw new Error("Unsupported domain verification method id");
1004
- }
1005
- methods.push(method);
1006
- }
1007
- domainVerifications.push({
1008
- domain,
1009
- ...(methods.length > 0 ? { methods } : {}),
1010
- });
1011
- }
1012
- }
1013
- }
1014
- let githubVerifications;
1015
- if (version >= DOMAIN_VERIFICATION_METADATA_VERSION) {
1016
- checkBounds(offset, 1, data.length - 65);
1017
- const githubVerificationCount = data[offset];
1018
- offset += 1;
1019
- if (githubVerificationCount > 0) {
1020
- githubVerifications = [];
1021
- for (let i = 0; i < githubVerificationCount; i += 1) {
1022
- checkBounds(offset, 1, data.length - 65);
1023
- const usernameLen = data[offset];
1024
- offset += 1;
1025
- checkBounds(offset, usernameLen, data.length - 65);
1026
- const username = new TextDecoder().decode(data.slice(offset, offset + usernameLen));
1027
- offset += usernameLen;
1028
- checkBounds(offset, 1, data.length - 65);
1029
- const repositoryLen = data[offset];
1030
- offset += 1;
1031
- checkBounds(offset, repositoryLen, data.length - 65);
1032
- const repository = new TextDecoder().decode(data.slice(offset, offset + repositoryLen));
1033
- offset += repositoryLen;
1034
- githubVerifications.push({
1035
- username,
1036
- ...(repository.length > 0 ? { repository } : {}),
1037
- });
1038
- }
1039
- }
1040
- }
1041
- // offerings
1042
- const PRICING_UNIT_REVERSE = ['token', 'request', 'minute', 'task'];
1043
- let offerings;
1044
- const remainingBeforeSignature = data.length - offset - 65;
1045
- if (remainingBeforeSignature >= 2) {
1046
- offerings = [];
1047
- checkBounds(offset, 2, data.length - 65);
1048
- const offeringCount = new DataView(data.buffer, data.byteOffset + offset, 2).getUint16(0, false);
1049
- offset += 2;
1050
- for (let i = 0; i < offeringCount; i++) {
1051
- checkBounds(offset, 1, data.length - 65);
1052
- const capLen = data[offset];
1053
- offset += 1;
1054
- checkBounds(offset, capLen, data.length - 65);
1055
- const capability = new TextDecoder().decode(data.slice(offset, offset + capLen));
1056
- offset += capLen;
1057
- checkBounds(offset, 1, data.length - 65);
1058
- const nameLen = data[offset];
1059
- offset += 1;
1060
- checkBounds(offset, nameLen, data.length - 65);
1061
- const name = new TextDecoder().decode(data.slice(offset, offset + nameLen));
1062
- offset += nameLen;
1063
- checkBounds(offset, 2, data.length - 65);
1064
- const descLen = new DataView(data.buffer, data.byteOffset + offset, 2).getUint16(0, false);
1065
- offset += 2;
1066
- checkBounds(offset, descLen, data.length - 65);
1067
- const description = new TextDecoder().decode(data.slice(offset, offset + descLen));
1068
- offset += descLen;
1069
- checkBounds(offset, 1, data.length - 65);
1070
- const unit = PRICING_UNIT_REVERSE[data[offset]] ?? 'token';
1071
- offset += 1;
1072
- checkBounds(offset, 4, data.length - 65);
1073
- const pricePerUnit = new DataView(data.buffer, data.byteOffset + offset, 4).getFloat32(0, false);
1074
- offset += 4;
1075
- checkBounds(offset, 1, data.length - 65);
1076
- const offeringServiceCount = data[offset];
1077
- offset += 1;
1078
- const offeringServices = [];
1079
- for (let j = 0; j < offeringServiceCount; j++) {
1080
- checkBounds(offset, 1, data.length - 65);
1081
- const serviceLen = data[offset];
1082
- offset += 1;
1083
- checkBounds(offset, serviceLen, data.length - 65);
1084
- offeringServices.push(new TextDecoder().decode(data.slice(offset, offset + serviceLen)));
1085
- offset += serviceLen;
1086
- }
1087
- offerings.push({
1088
- capability: capability,
1089
- name, description,
1090
- services: offeringServices.length > 0 ? offeringServices : undefined,
1091
- pricing: { unit, pricePerUnit, currency: 'USD' },
1092
- });
1093
- }
1094
- }
1095
- // Optional on-chain stats (flag + 10 bytes)
1096
- let onChainChannelCount;
1097
- let onChainGhostCount;
1098
- const remainingBeforeRepSig = data.length - offset - 65;
1099
- if (remainingBeforeRepSig >= 1) {
1100
- const repFlag = data[offset];
1101
- offset += 1;
1102
- if (repFlag === 1) {
1103
- checkBounds(offset, 10, data.length - 65);
1104
- const repView = new DataView(data.buffer, data.byteOffset + offset, 10);
1105
- // byte 0 is legacy reputation (ignored — use channelCount directly)
1106
- onChainChannelCount = repView.getUint32(1, false);
1107
- onChainGhostCount = repView.getUint32(5, false);
1108
- // byte 9 is reserved
1109
- offset += 10;
1110
- }
1111
- }
1112
- let capabilities;
1113
- if (version >= PEER_CAPABILITIES_METADATA_VERSION) {
1114
- checkBounds(offset, 1, data.length - 65);
1115
- const capabilityCount = data[offset];
1116
- offset += 1;
1117
- if (capabilityCount > 0) {
1118
- capabilities = [];
1119
- for (let i = 0; i < capabilityCount; i++) {
1120
- checkBounds(offset, 1, data.length - 65);
1121
- const capabilityLen = data[offset];
1122
- offset += 1;
1123
- checkBounds(offset, capabilityLen, data.length - 65);
1124
- const capability = new TextDecoder().decode(data.slice(offset, offset + capabilityLen));
1125
- offset += capabilityLen;
1126
- capabilities.push(capability);
1127
- }
1128
- }
1129
- }
1130
- // signature: 65 bytes (secp256k1 r+s+v)
1131
- checkBounds(offset, 65, data.length);
1132
- const signatureBytes = data.slice(offset, offset + 65);
1133
- const signature = bytesToHex(signatureBytes);
1134
- const verifications = {
1135
- ...(domainVerifications && domainVerifications.length > 0 ? { domains: domainVerifications } : {}),
1136
- ...(githubVerifications && githubVerifications.length > 0 ? { github: githubVerifications } : {}),
1137
- };
1138
- return {
1139
- peerId: toPeerId(peerId),
1140
- version,
1141
- ...(displayName ? { displayName } : {}),
1142
- ...(publicAddress ? { publicAddress } : {}),
1143
- providers,
1144
- ...(offerings && offerings.length > 0 ? { offerings } : {}),
1145
- ...(onChainChannelCount !== undefined ? { onChainChannelCount } : {}),
1146
- ...(onChainGhostCount !== undefined ? { onChainGhostCount } : {}),
1147
- ...(capabilities && capabilities.length > 0 ? { capabilities } : {}),
1148
- ...(sellerContract ? { sellerContract } : {}),
1149
- ...(Object.keys(verifications).length > 0 ? { verifications } : {}),
1150
- region,
1151
- timestamp,
1152
- signature,
1153
- };
1154
- }
1
+ // The codec is split into shared field modules and one file per version
2
+ // under ./metadata/; this module keeps the old import path working.
3
+ export { decodeMetadata, encodeMetadata, encodeMetadataForSigning, getMetadataCodec, negotiateMetadataVersion, SERVED_METADATA_VERSIONS, } from "./metadata/index.js";
1155
4
  //# sourceMappingURL=metadata-codec.js.map