@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.
- package/dist/cjs/mod.js +4 -0
- package/dist/cjs/mod.js.map +1 -1
- package/dist/cjs/package.json +4 -3
- package/dist/cjs/src/auth/Certificate.js +163 -0
- package/dist/cjs/src/auth/Certificate.js.map +1 -0
- package/dist/cjs/src/auth/index.js +9 -0
- package/dist/cjs/src/auth/index.js.map +1 -0
- package/dist/cjs/src/compat/BSM.js +17 -7
- package/dist/cjs/src/compat/BSM.js.map +1 -1
- package/dist/cjs/src/compat/ECIES.js +17 -7
- package/dist/cjs/src/compat/ECIES.js.map +1 -1
- package/dist/cjs/src/compat/HD.js +17 -7
- package/dist/cjs/src/compat/HD.js.map +1 -1
- package/dist/cjs/src/compat/Mnemonic.js +17 -7
- package/dist/cjs/src/compat/Mnemonic.js.map +1 -1
- package/dist/cjs/src/compat/index.js +17 -7
- package/dist/cjs/src/compat/index.js.map +1 -1
- package/dist/cjs/src/messages/index.js +17 -7
- package/dist/cjs/src/messages/index.js.map +1 -1
- package/dist/cjs/src/overlay-tools/LookupResolver.js +170 -0
- package/dist/cjs/src/overlay-tools/LookupResolver.js.map +1 -0
- package/dist/cjs/src/overlay-tools/OverlayAdminTokenTemplate.js +69 -0
- package/dist/cjs/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -0
- package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js +336 -0
- package/dist/cjs/src/overlay-tools/SHIPBroadcaster.js.map +1 -0
- package/dist/cjs/src/overlay-tools/index.js +29 -0
- package/dist/cjs/src/overlay-tools/index.js.map +1 -0
- package/dist/cjs/src/primitives/PrivateKey.js +17 -7
- package/dist/cjs/src/primitives/PrivateKey.js.map +1 -1
- package/dist/cjs/src/primitives/TransactionSignature.js +17 -7
- package/dist/cjs/src/primitives/TransactionSignature.js.map +1 -1
- package/dist/cjs/src/primitives/index.js +17 -7
- package/dist/cjs/src/primitives/index.js.map +1 -1
- package/dist/cjs/src/script/Spend.js +17 -7
- package/dist/cjs/src/script/Spend.js.map +1 -1
- package/dist/cjs/src/script/templates/PushDrop.js +218 -0
- package/dist/cjs/src/script/templates/PushDrop.js.map +1 -0
- package/dist/cjs/src/script/templates/index.js +3 -1
- package/dist/cjs/src/script/templates/index.js.map +1 -1
- package/dist/cjs/src/transaction/http/DefaultHttpClient.js +1 -1
- package/dist/cjs/src/transaction/http/DefaultHttpClient.js.map +1 -1
- package/dist/cjs/src/wallet/CachedKeyDeriver.js +177 -0
- package/dist/cjs/src/wallet/CachedKeyDeriver.js.map +1 -0
- package/dist/cjs/src/wallet/KeyDeriver.js +174 -0
- package/dist/cjs/src/wallet/KeyDeriver.js.map +1 -0
- package/dist/cjs/src/wallet/ProtoWallet.js +245 -0
- package/dist/cjs/src/wallet/ProtoWallet.js.map +1 -0
- package/dist/cjs/src/wallet/Wallet.interfaces.js +3 -0
- package/dist/cjs/src/wallet/Wallet.interfaces.js.map +1 -0
- package/dist/cjs/src/wallet/WalletClient.js +181 -0
- package/dist/cjs/src/wallet/WalletClient.js.map +1 -0
- package/dist/cjs/src/wallet/WalletError.js +28 -0
- package/dist/cjs/src/wallet/WalletError.js.map +1 -0
- package/dist/cjs/src/wallet/index.js +34 -0
- package/dist/cjs/src/wallet/index.js.map +1 -0
- package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js +45 -0
- package/dist/cjs/src/wallet/substrates/HTTPWalletWire.js.map +1 -0
- package/dist/cjs/src/wallet/substrates/WalletWire.js +3 -0
- package/dist/cjs/src/wallet/substrates/WalletWire.js.map +1 -0
- package/dist/cjs/src/wallet/substrates/WalletWireCalls.js +36 -0
- package/dist/cjs/src/wallet/substrates/WalletWireCalls.js.map +1 -0
- package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js +1821 -0
- package/dist/cjs/src/wallet/substrates/WalletWireProcessor.js.map +1 -0
- package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js +1305 -0
- package/dist/cjs/src/wallet/substrates/WalletWireTransceiver.js.map +1 -0
- package/dist/cjs/src/wallet/substrates/XDM.js +130 -0
- package/dist/cjs/src/wallet/substrates/XDM.js.map +1 -0
- package/dist/cjs/src/wallet/substrates/index.js +33 -0
- package/dist/cjs/src/wallet/substrates/index.js.map +1 -0
- package/dist/cjs/src/wallet/substrates/window.CWI.js +102 -0
- package/dist/cjs/src/wallet/substrates/window.CWI.js.map +1 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/mod.js +4 -0
- package/dist/esm/mod.js.map +1 -1
- package/dist/esm/src/auth/Certificate.js +185 -0
- package/dist/esm/src/auth/Certificate.js.map +1 -0
- package/dist/esm/src/auth/index.js +2 -0
- package/dist/esm/src/auth/index.js.map +1 -0
- package/dist/esm/src/overlay-tools/LookupResolver.js +167 -0
- package/dist/esm/src/overlay-tools/LookupResolver.js.map +1 -0
- package/dist/esm/src/overlay-tools/OverlayAdminTokenTemplate.js +64 -0
- package/dist/esm/src/overlay-tools/OverlayAdminTokenTemplate.js.map +1 -0
- package/dist/esm/src/overlay-tools/SHIPBroadcaster.js +335 -0
- package/dist/esm/src/overlay-tools/SHIPBroadcaster.js.map +1 -0
- package/dist/esm/src/overlay-tools/index.js +6 -0
- package/dist/esm/src/overlay-tools/index.js.map +1 -0
- package/dist/esm/src/script/templates/PushDrop.js +215 -0
- package/dist/esm/src/script/templates/PushDrop.js.map +1 -0
- package/dist/esm/src/script/templates/index.js +1 -0
- package/dist/esm/src/script/templates/index.js.map +1 -1
- package/dist/esm/src/transaction/http/DefaultHttpClient.js +1 -1
- package/dist/esm/src/transaction/http/DefaultHttpClient.js.map +1 -1
- package/dist/esm/src/wallet/CachedKeyDeriver.js +174 -0
- package/dist/esm/src/wallet/CachedKeyDeriver.js.map +1 -0
- package/dist/esm/src/wallet/KeyDeriver.js +172 -0
- package/dist/esm/src/wallet/KeyDeriver.js.map +1 -0
- package/dist/esm/src/wallet/ProtoWallet.js +207 -0
- package/dist/esm/src/wallet/ProtoWallet.js.map +1 -0
- package/dist/esm/src/wallet/Wallet.interfaces.js +2 -0
- package/dist/esm/src/wallet/Wallet.interfaces.js.map +1 -0
- package/dist/esm/src/wallet/WalletClient.js +177 -0
- package/dist/esm/src/wallet/WalletClient.js.map +1 -0
- package/dist/esm/src/wallet/WalletError.js +25 -0
- package/dist/esm/src/wallet/WalletError.js.map +1 -0
- package/dist/esm/src/wallet/index.js +9 -0
- package/dist/esm/src/wallet/index.js.map +1 -0
- package/dist/esm/src/wallet/substrates/HTTPWalletWire.js +42 -0
- package/dist/esm/src/wallet/substrates/HTTPWalletWire.js.map +1 -0
- package/dist/esm/src/wallet/substrates/WalletWire.js +2 -0
- package/dist/esm/src/wallet/substrates/WalletWire.js.map +1 -0
- package/dist/esm/src/wallet/substrates/WalletWireCalls.js +34 -0
- package/dist/esm/src/wallet/substrates/WalletWireCalls.js.map +1 -0
- package/dist/esm/src/wallet/substrates/WalletWireProcessor.js +1816 -0
- package/dist/esm/src/wallet/substrates/WalletWireProcessor.js.map +1 -0
- package/dist/esm/src/wallet/substrates/WalletWireTransceiver.js +1300 -0
- package/dist/esm/src/wallet/substrates/WalletWireTransceiver.js.map +1 -0
- package/dist/esm/src/wallet/substrates/XDM.js +128 -0
- package/dist/esm/src/wallet/substrates/XDM.js.map +1 -0
- package/dist/esm/src/wallet/substrates/index.js +8 -0
- package/dist/esm/src/wallet/substrates/index.js.map +1 -0
- package/dist/esm/src/wallet/substrates/window.CWI.js +100 -0
- package/dist/esm/src/wallet/substrates/window.CWI.js.map +1 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/mod.d.ts +4 -0
- package/dist/types/mod.d.ts.map +1 -1
- package/dist/types/src/auth/Certificate.d.ts +76 -0
- package/dist/types/src/auth/Certificate.d.ts.map +1 -0
- package/dist/types/src/auth/index.d.ts +2 -0
- package/dist/types/src/auth/index.d.ts.map +1 -0
- package/dist/types/src/overlay-tools/LookupResolver.d.ts +71 -0
- package/dist/types/src/overlay-tools/LookupResolver.d.ts.map +1 -0
- package/dist/types/src/overlay-tools/OverlayAdminTokenTemplate.d.ts +44 -0
- package/dist/types/src/overlay-tools/OverlayAdminTokenTemplate.d.ts.map +1 -0
- package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts +90 -0
- package/dist/types/src/overlay-tools/SHIPBroadcaster.d.ts.map +1 -0
- package/dist/types/src/overlay-tools/index.d.ts +6 -0
- package/dist/types/src/overlay-tools/index.d.ts.map +1 -0
- package/dist/types/src/script/templates/PushDrop.d.ts +53 -0
- package/dist/types/src/script/templates/PushDrop.d.ts.map +1 -0
- package/dist/types/src/script/templates/index.d.ts +1 -0
- package/dist/types/src/script/templates/index.d.ts.map +1 -1
- package/dist/types/src/wallet/CachedKeyDeriver.d.ts +92 -0
- package/dist/types/src/wallet/CachedKeyDeriver.d.ts.map +1 -0
- package/dist/types/src/wallet/KeyDeriver.d.ts +72 -0
- package/dist/types/src/wallet/KeyDeriver.d.ts.map +1 -0
- package/dist/types/src/wallet/ProtoWallet.d.ts +415 -0
- package/dist/types/src/wallet/ProtoWallet.d.ts.map +1 -0
- package/dist/types/src/wallet/Wallet.interfaces.d.ts +996 -0
- package/dist/types/src/wallet/Wallet.interfaces.d.ts.map +1 -0
- package/dist/types/src/wallet/WalletClient.d.ts +182 -0
- package/dist/types/src/wallet/WalletClient.d.ts.map +1 -0
- package/dist/types/src/wallet/WalletError.d.ts +14 -0
- package/dist/types/src/wallet/WalletError.d.ts.map +1 -0
- package/dist/types/src/wallet/index.d.ts +9 -0
- package/dist/types/src/wallet/index.d.ts.map +1 -0
- package/dist/types/src/wallet/substrates/HTTPWalletWire.d.ts +9 -0
- package/dist/types/src/wallet/substrates/HTTPWalletWire.d.ts.map +1 -0
- package/dist/types/src/wallet/substrates/WalletWire.d.ts +7 -0
- package/dist/types/src/wallet/substrates/WalletWire.d.ts.map +1 -0
- package/dist/types/src/wallet/substrates/WalletWireCalls.d.ts +33 -0
- package/dist/types/src/wallet/substrates/WalletWireCalls.d.ts.map +1 -0
- package/dist/types/src/wallet/substrates/WalletWireProcessor.d.ts +18 -0
- package/dist/types/src/wallet/substrates/WalletWireProcessor.d.ts.map +1 -0
- package/dist/types/src/wallet/substrates/WalletWireTransceiver.d.ts +196 -0
- package/dist/types/src/wallet/substrates/WalletWireTransceiver.d.ts.map +1 -0
- package/dist/types/src/wallet/substrates/XDM.d.ts +412 -0
- package/dist/types/src/wallet/substrates/XDM.d.ts.map +1 -0
- package/dist/types/src/wallet/substrates/index.d.ts +8 -0
- package/dist/types/src/wallet/substrates/index.d.ts.map +1 -0
- package/dist/types/src/wallet/substrates/window.CWI.d.ts +410 -0
- package/dist/types/src/wallet/substrates/window.CWI.d.ts.map +1 -0
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +1 -1
- package/docs/overlay-tools.md +551 -0
- package/docs/script.md +135 -0
- package/docs/totp.md +119 -0
- package/docs/wallet-substrates.md +10 -0
- package/docs/wallet.md +4182 -0
- package/mod.ts +5 -1
- package/package.json +44 -3
- package/src/auth/Certificate.ts +233 -0
- package/src/auth/__tests/Certificate.test.ts +282 -0
- package/src/auth/index.ts +1 -0
- package/src/overlay-tools/LookupResolver.ts +228 -0
- package/src/overlay-tools/OverlayAdminTokenTemplate.ts +79 -0
- package/src/overlay-tools/SHIPBroadcaster.ts +405 -0
- package/src/overlay-tools/__tests/LookupResolver.test.ts +1403 -0
- package/src/overlay-tools/__tests/OverlayAdminTokenTemplate.test.ts +69 -0
- package/src/overlay-tools/__tests/SHIPBroadcaster.test.ts +904 -0
- package/src/overlay-tools/index.ts +5 -0
- package/src/script/templates/PushDrop.ts +246 -0
- package/src/script/templates/__tests/PushDrop.test.ts +158 -0
- package/src/script/templates/index.ts +1 -0
- package/src/transaction/http/DefaultHttpClient.ts +1 -1
- package/src/wallet/CachedKeyDeriver.ts +193 -0
- package/src/wallet/KeyDeriver.ts +178 -0
- package/src/wallet/ProtoWallet.ts +732 -0
- package/src/wallet/Wallet.interfaces.ts +1170 -0
- package/src/wallet/WalletClient.ts +201 -0
- package/src/wallet/WalletError.ts +27 -0
- package/src/wallet/__tests/CachedKeyDeriver.test.ts +322 -0
- package/src/wallet/__tests/KeyDeriver.test.ts +118 -0
- package/src/wallet/__tests/ProtoWallet.test.ts +543 -0
- package/src/wallet/index.ts +8 -0
- package/src/wallet/substrates/HTTPWalletWire.ts +47 -0
- package/src/wallet/substrates/WalletWire.ts +6 -0
- package/src/wallet/substrates/WalletWireCalls.ts +34 -0
- package/src/wallet/substrates/WalletWireProcessor.ts +2046 -0
- package/src/wallet/substrates/WalletWireTransceiver.ts +1454 -0
- package/src/wallet/substrates/XDM.ts +157 -0
- package/src/wallet/substrates/__tests/WalletWire.integration.test.ts +2194 -0
- package/src/wallet/substrates/__tests/XDM.test.ts +659 -0
- package/src/wallet/substrates/index.ts +7 -0
- 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
|
+
}
|