@bsv/sdk 1.1.33 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/dist/cjs/mod.js +4 -0
  2. package/dist/cjs/mod.js.map +1 -1
  3. package/dist/cjs/package.json +4 -3
  4. package/dist/cjs/src/auth/Certificate.js +163 -0
  5. package/dist/cjs/src/auth/Certificate.js.map +1 -0
  6. package/dist/cjs/src/auth/index.js +9 -0
  7. package/dist/cjs/src/auth/index.js.map +1 -0
  8. package/dist/cjs/src/compat/BSM.js +17 -7
  9. package/dist/cjs/src/compat/BSM.js.map +1 -1
  10. package/dist/cjs/src/compat/ECIES.js +17 -7
  11. package/dist/cjs/src/compat/ECIES.js.map +1 -1
  12. package/dist/cjs/src/compat/HD.js +17 -7
  13. package/dist/cjs/src/compat/HD.js.map +1 -1
  14. package/dist/cjs/src/compat/Mnemonic.js +17 -7
  15. package/dist/cjs/src/compat/Mnemonic.js.map +1 -1
  16. package/dist/cjs/src/compat/index.js +17 -7
  17. package/dist/cjs/src/compat/index.js.map +1 -1
  18. package/dist/cjs/src/messages/index.js +17 -7
  19. package/dist/cjs/src/messages/index.js.map +1 -1
  20. package/dist/cjs/src/overlay-tools/LookupResolver.js +170 -0
  21. package/dist/cjs/src/overlay-tools/LookupResolver.js.map +1 -0
  22. package/dist/cjs/src/overlay-tools/OverlayAdminTokenTemplate.js +69 -0
  23. package/dist/cjs/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -0
  24. package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js +336 -0
  25. package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js.map +1 -0
  26. package/dist/cjs/src/overlay-tools/index.js +29 -0
  27. package/dist/cjs/src/overlay-tools/index.js.map +1 -0
  28. package/dist/cjs/src/primitives/PrivateKey.js +17 -7
  29. package/dist/cjs/src/primitives/PrivateKey.js.map +1 -1
  30. package/dist/cjs/src/primitives/TransactionSignature.js +17 -7
  31. package/dist/cjs/src/primitives/TransactionSignature.js.map +1 -1
  32. package/dist/cjs/src/primitives/index.js +17 -7
  33. package/dist/cjs/src/primitives/index.js.map +1 -1
  34. package/dist/cjs/src/script/Spend.js +17 -7
  35. package/dist/cjs/src/script/Spend.js.map +1 -1
  36. package/dist/cjs/src/script/templates/PushDrop.js +218 -0
  37. package/dist/cjs/src/script/templates/PushDrop.js.map +1 -0
  38. package/dist/cjs/src/script/templates/index.js +3 -1
  39. package/dist/cjs/src/script/templates/index.js.map +1 -1
  40. package/dist/cjs/src/transaction/http/DefaultHttpClient.js +1 -1
  41. package/dist/cjs/src/transaction/http/DefaultHttpClient.js.map +1 -1
  42. package/dist/cjs/src/wallet/CachedKeyDeriver.js +177 -0
  43. package/dist/cjs/src/wallet/CachedKeyDeriver.js.map +1 -0
  44. package/dist/cjs/src/wallet/KeyDeriver.js +174 -0
  45. package/dist/cjs/src/wallet/KeyDeriver.js.map +1 -0
  46. package/dist/cjs/src/wallet/ProtoWallet.js +245 -0
  47. package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -0
  48. package/dist/cjs/src/wallet/Wallet.interfaces.js +3 -0
  49. package/dist/cjs/src/wallet/Wallet.interfaces.js.map +1 -0
  50. package/dist/cjs/src/wallet/WalletClient.js +181 -0
  51. package/dist/cjs/src/wallet/WalletClient.js.map +1 -0
  52. package/dist/cjs/src/wallet/WalletError.js +28 -0
  53. package/dist/cjs/src/wallet/WalletError.js.map +1 -0
  54. package/dist/cjs/src/wallet/index.js +34 -0
  55. package/dist/cjs/src/wallet/index.js.map +1 -0
  56. package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js +45 -0
  57. package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js.map +1 -0
  58. package/dist/cjs/src/wallet/substrates/WalletWire.js +3 -0
  59. package/dist/cjs/src/wallet/substrates/WalletWire.js.map +1 -0
  60. package/dist/cjs/src/wallet/substrates/WalletWireCalls.js +36 -0
  61. package/dist/cjs/src/wallet/substrates/WalletWireCalls.js.map +1 -0
  62. package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js +1821 -0
  63. package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js.map +1 -0
  64. package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js +1305 -0
  65. package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js.map +1 -0
  66. package/dist/cjs/src/wallet/substrates/XDM.js +130 -0
  67. package/dist/cjs/src/wallet/substrates/XDM.js.map +1 -0
  68. package/dist/cjs/src/wallet/substrates/index.js +33 -0
  69. package/dist/cjs/src/wallet/substrates/index.js.map +1 -0
  70. package/dist/cjs/src/wallet/substrates/window.CWI.js +102 -0
  71. package/dist/cjs/src/wallet/substrates/window.CWI.js.map +1 -0
  72. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  73. package/dist/esm/mod.js +4 -0
  74. package/dist/esm/mod.js.map +1 -1
  75. package/dist/esm/src/auth/Certificate.js +185 -0
  76. package/dist/esm/src/auth/Certificate.js.map +1 -0
  77. package/dist/esm/src/auth/index.js +2 -0
  78. package/dist/esm/src/auth/index.js.map +1 -0
  79. package/dist/esm/src/overlay-tools/LookupResolver.js +167 -0
  80. package/dist/esm/src/overlay-tools/LookupResolver.js.map +1 -0
  81. package/dist/esm/src/overlay-tools/OverlayAdminTokenTemplate.js +64 -0
  82. package/dist/esm/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -0
  83. package/dist/esm/src/overlay-tools/SHIPBroadcaster.js +335 -0
  84. package/dist/esm/src/overlay-tools/SHIPBroadcaster.js.map +1 -0
  85. package/dist/esm/src/overlay-tools/index.js +6 -0
  86. package/dist/esm/src/overlay-tools/index.js.map +1 -0
  87. package/dist/esm/src/script/templates/PushDrop.js +215 -0
  88. package/dist/esm/src/script/templates/PushDrop.js.map +1 -0
  89. package/dist/esm/src/script/templates/index.js +1 -0
  90. package/dist/esm/src/script/templates/index.js.map +1 -1
  91. package/dist/esm/src/transaction/http/DefaultHttpClient.js +1 -1
  92. package/dist/esm/src/transaction/http/DefaultHttpClient.js.map +1 -1
  93. package/dist/esm/src/wallet/CachedKeyDeriver.js +174 -0
  94. package/dist/esm/src/wallet/CachedKeyDeriver.js.map +1 -0
  95. package/dist/esm/src/wallet/KeyDeriver.js +172 -0
  96. package/dist/esm/src/wallet/KeyDeriver.js.map +1 -0
  97. package/dist/esm/src/wallet/ProtoWallet.js +207 -0
  98. package/dist/esm/src/wallet/ProtoWallet.js.map +1 -0
  99. package/dist/esm/src/wallet/Wallet.interfaces.js +2 -0
  100. package/dist/esm/src/wallet/Wallet.interfaces.js.map +1 -0
  101. package/dist/esm/src/wallet/WalletClient.js +177 -0
  102. package/dist/esm/src/wallet/WalletClient.js.map +1 -0
  103. package/dist/esm/src/wallet/WalletError.js +25 -0
  104. package/dist/esm/src/wallet/WalletError.js.map +1 -0
  105. package/dist/esm/src/wallet/index.js +9 -0
  106. package/dist/esm/src/wallet/index.js.map +1 -0
  107. package/dist/esm/src/wallet/substrates/HTTPWalletWire.js +42 -0
  108. package/dist/esm/src/wallet/substrates/HTTPWalletWire.js.map +1 -0
  109. package/dist/esm/src/wallet/substrates/WalletWire.js +2 -0
  110. package/dist/esm/src/wallet/substrates/WalletWire.js.map +1 -0
  111. package/dist/esm/src/wallet/substrates/WalletWireCalls.js +34 -0
  112. package/dist/esm/src/wallet/substrates/WalletWireCalls.js.map +1 -0
  113. package/dist/esm/src/wallet/substrates/WalletWireProcessor.js +1816 -0
  114. package/dist/esm/src/wallet/substrates/WalletWireProcessor.js.map +1 -0
  115. package/dist/esm/src/wallet/substrates/WalletWireTransceiver.js +1300 -0
  116. package/dist/esm/src/wallet/substrates/WalletWireTransceiver.js.map +1 -0
  117. package/dist/esm/src/wallet/substrates/XDM.js +128 -0
  118. package/dist/esm/src/wallet/substrates/XDM.js.map +1 -0
  119. package/dist/esm/src/wallet/substrates/index.js +8 -0
  120. package/dist/esm/src/wallet/substrates/index.js.map +1 -0
  121. package/dist/esm/src/wallet/substrates/window.CWI.js +100 -0
  122. package/dist/esm/src/wallet/substrates/window.CWI.js.map +1 -0
  123. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  124. package/dist/types/mod.d.ts +4 -0
  125. package/dist/types/mod.d.ts.map +1 -1
  126. package/dist/types/src/auth/Certificate.d.ts +76 -0
  127. package/dist/types/src/auth/Certificate.d.ts.map +1 -0
  128. package/dist/types/src/auth/index.d.ts +2 -0
  129. package/dist/types/src/auth/index.d.ts.map +1 -0
  130. package/dist/types/src/overlay-tools/LookupResolver.d.ts +71 -0
  131. package/dist/types/src/overlay-tools/LookupResolver.d.ts.map +1 -0
  132. package/dist/types/src/overlay-tools/OverlayAdminTokenTemplate.d.ts +44 -0
  133. package/dist/types/src/overlay-tools/OverlayAdminTokenTemplate.d.ts.map +1 -0
  134. package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts +90 -0
  135. package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts.map +1 -0
  136. package/dist/types/src/overlay-tools/index.d.ts +6 -0
  137. package/dist/types/src/overlay-tools/index.d.ts.map +1 -0
  138. package/dist/types/src/script/templates/PushDrop.d.ts +53 -0
  139. package/dist/types/src/script/templates/PushDrop.d.ts.map +1 -0
  140. package/dist/types/src/script/templates/index.d.ts +1 -0
  141. package/dist/types/src/script/templates/index.d.ts.map +1 -1
  142. package/dist/types/src/wallet/CachedKeyDeriver.d.ts +92 -0
  143. package/dist/types/src/wallet/CachedKeyDeriver.d.ts.map +1 -0
  144. package/dist/types/src/wallet/KeyDeriver.d.ts +72 -0
  145. package/dist/types/src/wallet/KeyDeriver.d.ts.map +1 -0
  146. package/dist/types/src/wallet/ProtoWallet.d.ts +415 -0
  147. package/dist/types/src/wallet/ProtoWallet.d.ts.map +1 -0
  148. package/dist/types/src/wallet/Wallet.interfaces.d.ts +996 -0
  149. package/dist/types/src/wallet/Wallet.interfaces.d.ts.map +1 -0
  150. package/dist/types/src/wallet/WalletClient.d.ts +182 -0
  151. package/dist/types/src/wallet/WalletClient.d.ts.map +1 -0
  152. package/dist/types/src/wallet/WalletError.d.ts +14 -0
  153. package/dist/types/src/wallet/WalletError.d.ts.map +1 -0
  154. package/dist/types/src/wallet/index.d.ts +9 -0
  155. package/dist/types/src/wallet/index.d.ts.map +1 -0
  156. package/dist/types/src/wallet/substrates/HTTPWalletWire.d.ts +9 -0
  157. package/dist/types/src/wallet/substrates/HTTPWalletWire.d.ts.map +1 -0
  158. package/dist/types/src/wallet/substrates/WalletWire.d.ts +7 -0
  159. package/dist/types/src/wallet/substrates/WalletWire.d.ts.map +1 -0
  160. package/dist/types/src/wallet/substrates/WalletWireCalls.d.ts +33 -0
  161. package/dist/types/src/wallet/substrates/WalletWireCalls.d.ts.map +1 -0
  162. package/dist/types/src/wallet/substrates/WalletWireProcessor.d.ts +18 -0
  163. package/dist/types/src/wallet/substrates/WalletWireProcessor.d.ts.map +1 -0
  164. package/dist/types/src/wallet/substrates/WalletWireTransceiver.d.ts +196 -0
  165. package/dist/types/src/wallet/substrates/WalletWireTransceiver.d.ts.map +1 -0
  166. package/dist/types/src/wallet/substrates/XDM.d.ts +412 -0
  167. package/dist/types/src/wallet/substrates/XDM.d.ts.map +1 -0
  168. package/dist/types/src/wallet/substrates/index.d.ts +8 -0
  169. package/dist/types/src/wallet/substrates/index.d.ts.map +1 -0
  170. package/dist/types/src/wallet/substrates/window.CWI.d.ts +410 -0
  171. package/dist/types/src/wallet/substrates/window.CWI.d.ts.map +1 -0
  172. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  173. package/dist/umd/bundle.js +1 -1
  174. package/docs/overlay-tools.md +551 -0
  175. package/docs/script.md +135 -0
  176. package/docs/totp.md +119 -0
  177. package/docs/wallet-substrates.md +10 -0
  178. package/docs/wallet.md +4182 -0
  179. package/mod.ts +5 -1
  180. package/package.json +44 -3
  181. package/src/auth/Certificate.ts +233 -0
  182. package/src/auth/__tests/Certificate.test.ts +282 -0
  183. package/src/auth/index.ts +1 -0
  184. package/src/overlay-tools/LookupResolver.ts +228 -0
  185. package/src/overlay-tools/OverlayAdminTokenTemplate.ts +79 -0
  186. package/src/overlay-tools/SHIPBroadcaster.ts +405 -0
  187. package/src/overlay-tools/__tests/LookupResolver.test.ts +1403 -0
  188. package/src/overlay-tools/__tests/OverlayAdminTokenTemplate.test.ts +69 -0
  189. package/src/overlay-tools/__tests/SHIPBroadcaster.test.ts +904 -0
  190. package/src/overlay-tools/index.ts +5 -0
  191. package/src/script/templates/PushDrop.ts +246 -0
  192. package/src/script/templates/__tests/PushDrop.test.ts +158 -0
  193. package/src/script/templates/index.ts +1 -0
  194. package/src/transaction/http/DefaultHttpClient.ts +1 -1
  195. package/src/wallet/CachedKeyDeriver.ts +193 -0
  196. package/src/wallet/KeyDeriver.ts +178 -0
  197. package/src/wallet/ProtoWallet.ts +732 -0
  198. package/src/wallet/Wallet.interfaces.ts +1170 -0
  199. package/src/wallet/WalletClient.ts +201 -0
  200. package/src/wallet/WalletError.ts +27 -0
  201. package/src/wallet/__tests/CachedKeyDeriver.test.ts +322 -0
  202. package/src/wallet/__tests/KeyDeriver.test.ts +118 -0
  203. package/src/wallet/__tests/ProtoWallet.test.ts +543 -0
  204. package/src/wallet/index.ts +8 -0
  205. package/src/wallet/substrates/HTTPWalletWire.ts +47 -0
  206. package/src/wallet/substrates/WalletWire.ts +6 -0
  207. package/src/wallet/substrates/WalletWireCalls.ts +34 -0
  208. package/src/wallet/substrates/WalletWireProcessor.ts +2046 -0
  209. package/src/wallet/substrates/WalletWireTransceiver.ts +1454 -0
  210. package/src/wallet/substrates/XDM.ts +157 -0
  211. package/src/wallet/substrates/__tests/WalletWire.integration.test.ts +2194 -0
  212. package/src/wallet/substrates/__tests/XDM.test.ts +659 -0
  213. package/src/wallet/substrates/index.ts +7 -0
  214. package/src/wallet/substrates/window.CWI.ts +133 -0
@@ -0,0 +1,228 @@
1
+ import { Transaction } from '../transaction/index.js'
2
+ import OverlayAdminTokenTemplate from './OverlayAdminTokenTemplate.js'
3
+
4
+ /**
5
+ * The question asked to the Overlay Services Engine when a consumer of state wishes to look up information.
6
+ */
7
+ export interface LookupQuestion {
8
+ /**
9
+ * The identifier for a Lookup Service which the person asking the question wishes to use.
10
+ */
11
+ service: string
12
+
13
+ /**
14
+ * The query which will be forwarded to the Lookup Service.
15
+ * Its type depends on that prescribed by the Lookup Service employed.
16
+ */
17
+ query: unknown
18
+ }
19
+
20
+ /**
21
+ * How the Overlay Services Engine responds to a Lookup Question.
22
+ * It may comprise either an output list or a freeform response from the Lookup Service.
23
+ */
24
+ export type LookupAnswer = {
25
+ type: 'output-list'
26
+ outputs: Array<{
27
+ beef: number[]
28
+ outputIndex: number
29
+ }>
30
+ } | {
31
+ type: 'freeform'
32
+ result: unknown
33
+ }
34
+
35
+ /** Default SLAP trackers */
36
+ export const DEFAULT_SLAP_TRACKERS: string[] = [
37
+ // Babbage primary overlay service
38
+ 'https://overlay.babbage.systems',
39
+ // Babbage example overlay
40
+ 'https://overlay-example.babbage.systems',
41
+ // The Babbage office building
42
+ 'https://office.babbage.systems'
43
+
44
+ // NOTE: Other entities may submit pull requests to the library if they maintain SLAP overlay services.
45
+ // Additional trackers run by different entities contribute to greater network resiliency.
46
+ // It also generally doesn't hurt to have more trackers in this list.
47
+
48
+ // DISCLAIMER:
49
+ // Trackers known to host invalid or illegal records will be removed at the discretion of the BSV Association.
50
+ ]
51
+
52
+ /** Configuration options for the Lookup resolver. */
53
+ export interface LookupResolverConfig {
54
+ /** The facilitator used to make requests to Overlay Services hosts. */
55
+ facilitator?: OverlayLookupFacilitator
56
+ /** The list of SLAP trackers queried to resolve Overlay Services hosts for a given lookup service. */
57
+ slapTrackers?: string[]
58
+ /** Map of lookup service names to arrays of hosts to use in place of resolving via SLAP. */
59
+ hostOverrides?: Record<string, string[]>
60
+ /** Map of lookup service names to arrays of hosts to use in addition to resolving via SLAP. */
61
+ additionalHosts?: Record<string, string[]>
62
+ }
63
+
64
+ /** Facilitates lookups to URLs that return answers. */
65
+ export interface OverlayLookupFacilitator {
66
+ lookup: (url: string, question: LookupQuestion) => Promise<LookupAnswer>
67
+ }
68
+
69
+ export class HTTPSOverlayLookupFacilitator implements OverlayLookupFacilitator {
70
+ fetchClient: typeof fetch
71
+
72
+ constructor(httpClient = fetch) {
73
+ this.fetchClient = httpClient
74
+ }
75
+
76
+ async lookup(url: string, question: LookupQuestion): Promise<LookupAnswer> {
77
+ if (!url.startsWith('https:')) {
78
+ throw new Error('HTTPS facilitator can only use URLs that start with "https:"')
79
+ }
80
+ const response = await fetch(`${url}/lookup`, {
81
+ method: 'POST',
82
+ headers: {
83
+ 'Content-Type': 'application/json'
84
+ },
85
+ body: JSON.stringify({ service: question.service, query: question.query })
86
+ })
87
+ if (response.ok) {
88
+ return await response.json()
89
+ } else {
90
+ throw new Error('Failed to facilitate lookup')
91
+ }
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Represents an SHIP transaction broadcaster.
97
+ */
98
+ export default class LookupResolver {
99
+ private readonly facilitator: OverlayLookupFacilitator
100
+ private readonly slapTrackers: string[]
101
+ private readonly hostOverrides: Record<string, string[]>
102
+ private readonly additionalHosts: Record<string, string[]>
103
+
104
+ constructor(config?: LookupResolverConfig) {
105
+ const { facilitator, slapTrackers, hostOverrides, additionalHosts } = config ?? {} as LookupResolverConfig
106
+ this.facilitator = facilitator ?? new HTTPSOverlayLookupFacilitator()
107
+ this.slapTrackers = slapTrackers ?? DEFAULT_SLAP_TRACKERS
108
+ this.hostOverrides = hostOverrides ?? {}
109
+ this.additionalHosts = additionalHosts ?? {}
110
+ }
111
+
112
+ /**
113
+ * Given a LookupQuestion, returns a LookupAnswer. Aggregates across multiple services and supports resiliency.
114
+ */
115
+ async query(question: LookupQuestion): Promise<LookupAnswer> {
116
+ let competentHosts: string[] = []
117
+ if (question.service === 'ls_slap') {
118
+ competentHosts = this.slapTrackers
119
+ } else if (this.hostOverrides[question.service]) {
120
+ competentHosts = this.hostOverrides[question.service]
121
+ } else {
122
+ competentHosts = await this.findCompetentHosts(question.service)
123
+ }
124
+ if (this.additionalHosts[question.service]) {
125
+ competentHosts = [
126
+ ...competentHosts,
127
+ ...this.additionalHosts[question.service]
128
+ ]
129
+ }
130
+ if (competentHosts.length < 1) {
131
+ throw new Error(`No competent hosts found by the SLAP trackers for lookup service: ${question.service}`)
132
+ }
133
+
134
+ // Use Promise.allSettled to handle individual host failures
135
+ const hostResponses = await Promise.allSettled(
136
+ competentHosts.map(async host => await this.facilitator.lookup(host, question))
137
+ )
138
+
139
+ const successfulResponses = hostResponses
140
+ .filter(result => result.status === 'fulfilled')
141
+ .map(result => (result).value)
142
+
143
+ if (successfulResponses.length === 0) {
144
+ throw new Error('No successful responses from any hosts')
145
+ }
146
+
147
+ // Process the successful responses
148
+ if (successfulResponses[0].type === 'freeform') {
149
+ // Return the first freeform response
150
+ return successfulResponses[0]
151
+ } else {
152
+ // Aggregate outputs from all successful responses
153
+ const outputs = new Map<string, { beef: number[], outputIndex: number }>()
154
+ for (const response of successfulResponses) {
155
+ if (response.type !== 'output-list') {
156
+ continue
157
+ }
158
+ try {
159
+ for (const output of response.outputs) {
160
+ try {
161
+ const key = `${Transaction.fromBEEF(output.beef).id('hex')}.${output.outputIndex}`
162
+ outputs.set(key, output)
163
+ } catch (e) {
164
+ continue
165
+ }
166
+ }
167
+ } catch (e) {
168
+ continue
169
+ }
170
+ }
171
+ return {
172
+ type: 'output-list',
173
+ outputs: Array.from(outputs.values())
174
+ }
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Returns a list of competent hosts for a given lookup service.
180
+ * @param service Service for which competent hosts are to be returned
181
+ * @returns Array of hosts competent for resolving queries
182
+ */
183
+ private async findCompetentHosts(service: string): Promise<string[]> {
184
+ const query: LookupQuestion = {
185
+ service: 'ls_slap',
186
+ query: {
187
+ service
188
+ }
189
+ }
190
+
191
+ // Use Promise.allSettled to handle individual SLAP tracker failures
192
+ const trackerResponses = await Promise.allSettled(
193
+ this.slapTrackers.map(async tracker => await this.facilitator.lookup(tracker, query))
194
+ )
195
+
196
+ const hosts = new Set<string>()
197
+
198
+ for (const result of trackerResponses) {
199
+ if (result.status === 'fulfilled') {
200
+ const answer = result.value
201
+ if (answer.type !== 'output-list') {
202
+ // Log invalid response and continue
203
+ continue
204
+ }
205
+ for (const output of answer.outputs) {
206
+ try {
207
+ const tx = Transaction.fromBEEF(output.beef)
208
+ const script = tx.outputs[output.outputIndex].lockingScript
209
+ const parsed = OverlayAdminTokenTemplate.decode(script)
210
+ if (parsed.topicOrService !== service || parsed.protocol !== 'SLAP') {
211
+ // Invalid advertisement, skip
212
+ continue
213
+ }
214
+ hosts.add(parsed.domain)
215
+ } catch (e) {
216
+ // Invalid output, skip
217
+ continue
218
+ }
219
+ }
220
+ } else {
221
+ // Log tracker failure and continue
222
+ continue
223
+ }
224
+ }
225
+
226
+ return [...hosts]
227
+ }
228
+ }
@@ -0,0 +1,79 @@
1
+ import PushDrop from '../script/templates/PushDrop.js'
2
+ import { Wallet } from '../wallet/Wallet.interfaces.js'
3
+ import { LockingScript, ScriptTemplate, UnlockingScript } from '../script/index.js'
4
+ import { Transaction } from '../transaction/index.js'
5
+ import { Utils } from '../primitives/index.js'
6
+
7
+ /**
8
+ * Script template enabling the creation, unlocking, and decoding of SHIP and SLAP advertisements.
9
+ */
10
+ export default class OverlayAdminTokenTemplate implements ScriptTemplate {
11
+ pushDrop: PushDrop
12
+
13
+ /**
14
+ * Decodes a SHIP or SLAP advertisement from a given locking script.
15
+ * @param script Locking script comprising a SHIP or SLAP token to decode
16
+ * @returns Decoded SHIP or SLAP advertisement
17
+ */
18
+ static decode(script: LockingScript): { protocol: 'SHIP' | 'SLAP', identityKey: string, domain: string, topicOrService: string } {
19
+ const result = PushDrop.decode(script)
20
+ if (result.fields.length < 4) {
21
+ throw new Error('Invalid SHIP/SLAP advertisement!')
22
+ }
23
+ const protocol = Utils.toUTF8(result.fields[0])
24
+ if (protocol !== 'SHIP' && protocol !== 'SLAP') {
25
+ throw new Error('Invalid protocol type!')
26
+ }
27
+ const identityKey = Utils.toHex(result.fields[1])
28
+ const domain = Utils.toUTF8(result.fields[2])
29
+ const topicOrService = Utils.toUTF8(result.fields[3])
30
+ return {
31
+ protocol,
32
+ identityKey,
33
+ domain,
34
+ topicOrService
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Constructs a new Overlay Admin template instance
40
+ * @param wallet Wallet to use for locking and unlocking
41
+ */
42
+ constructor(wallet: Wallet) {
43
+ this.pushDrop = new PushDrop(wallet)
44
+ }
45
+
46
+ /**
47
+ * Creates a new advertisement locking script
48
+ * @param protocol SHIP or SLAP
49
+ * @param domain Domain where the topic or service is available
50
+ * @param topicOrService Topic or service to advertise
51
+ * @returns Locking script comprising the advertisement token
52
+ */
53
+ async lock(protocol: 'SHIP' | 'SLAP', domain: string, topicOrService: string): Promise<LockingScript> {
54
+ const { publicKey: identityKey } = await this.pushDrop.wallet.getPublicKey({ identityKey: true })
55
+ return await this.pushDrop.lock(
56
+ [
57
+ Utils.toArray(protocol, 'utf8'),
58
+ Utils.toArray(identityKey, 'hex'),
59
+ Utils.toArray(domain, 'utf8'),
60
+ Utils.toArray(topicOrService, 'utf8')
61
+ ],
62
+ [2, protocol === 'SHIP' ? 'Service Host Interconnect' : 'Service Lookup Availability'],
63
+ '1',
64
+ 'self'
65
+ )
66
+ }
67
+
68
+ /**
69
+ * Unlocks an advertisement token as part of a transaction.
70
+ * @param protocol SHIP or SLAP, depending on the token to unlock
71
+ * @returns Script unlocker capable of unlocking the advertisement token
72
+ */
73
+ unlock(protocol: 'SHIP' | 'SLAP'): {
74
+ sign: (tx: Transaction, inputIndex: number) => Promise<UnlockingScript>
75
+ estimateLength: (tx: Transaction, inputIndex: number) => Promise<number>
76
+ } {
77
+ return this.pushDrop.unlock([2, protocol === 'SHIP' ? 'Service Host Interconnect' : 'Service Lookup Availability'], '1', 'self')
78
+ }
79
+ }