@bsv/overlay-discovery-services 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/cjs/package.json +4 -4
  2. package/dist/cjs/src/LegacyNinjaAdvertiser.js +235 -0
  3. package/dist/cjs/src/LegacyNinjaAdvertiser.js.map +1 -0
  4. package/dist/cjs/src/utils/generateDocs.js +81 -0
  5. package/dist/cjs/src/utils/generateDocs.js.map +1 -0
  6. package/dist/cjs/src/utils/getDocumentation.js +22 -0
  7. package/dist/cjs/src/utils/getDocumentation.js.map +1 -0
  8. package/dist/cjs/src/utils/isValidDomain.js +15 -0
  9. package/dist/cjs/src/utils/isValidDomain.js.map +1 -0
  10. package/dist/cjs/src/utils/isValidServiceName.js +14 -0
  11. package/dist/cjs/src/utils/isValidServiceName.js.map +1 -0
  12. package/dist/cjs/src/utils/verifyToken.js +22 -0
  13. package/dist/cjs/src/utils/verifyToken.js.map +1 -0
  14. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  15. package/dist/esm/src/LegacyNinjaAdvertiser.js +233 -0
  16. package/dist/esm/src/LegacyNinjaAdvertiser.js.map +1 -0
  17. package/dist/esm/src/utils/generateDocs.js +46 -0
  18. package/dist/esm/src/utils/generateDocs.js.map +1 -0
  19. package/dist/esm/src/utils/getDocumentation.js +20 -0
  20. package/dist/esm/src/utils/getDocumentation.js.map +1 -0
  21. package/dist/esm/src/utils/isValidDomain.js +11 -0
  22. package/dist/esm/src/utils/isValidDomain.js.map +1 -0
  23. package/dist/esm/src/utils/isValidServiceName.js +10 -0
  24. package/dist/esm/src/utils/isValidServiceName.js.map +1 -0
  25. package/dist/esm/src/utils/verifyToken.js +18 -0
  26. package/dist/esm/src/utils/verifyToken.js.map +1 -0
  27. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  28. package/dist/types/src/LegacyNinjaAdvertiser.d.ts +60 -0
  29. package/dist/types/src/LegacyNinjaAdvertiser.d.ts.map +1 -0
  30. package/dist/types/src/utils/generateDocs.d.ts +2 -0
  31. package/dist/types/src/utils/generateDocs.d.ts.map +1 -0
  32. package/dist/types/src/utils/getDocumentation.d.ts +8 -0
  33. package/dist/types/src/utils/getDocumentation.d.ts.map +1 -0
  34. package/dist/types/src/utils/isValidDomain.d.ts +7 -0
  35. package/dist/types/src/utils/isValidDomain.d.ts.map +1 -0
  36. package/dist/types/src/utils/isValidServiceName.d.ts +7 -0
  37. package/dist/types/src/utils/isValidServiceName.d.ts.map +1 -0
  38. package/dist/types/src/utils/verifyToken.d.ts +12 -0
  39. package/dist/types/src/utils/verifyToken.d.ts.map +1 -0
  40. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  41. package/package.json +4 -4
@@ -0,0 +1,233 @@
1
+ import pushdrop from 'pushdrop';
2
+ import { Ninja } from 'ninja-base';
3
+ import { toBEEFfromEnvelope } from '@babbage/sdk-ts';
4
+ import { Transaction, PublicKey, PrivateKey } from '@bsv/sdk';
5
+ import { getPaymentPrivateKey } from 'sendover';
6
+ import { toEnvelopeFromBEEF } from '@babbage/sdk-ts/out/src/utils/toBEEF.js';
7
+ const AD_TOKEN_VALUE = 1;
8
+ // TODO: Add 'implements Advertiser' back, once Advertiser can be properly imported from Overlay Services.
9
+ /**
10
+ * Implements the Advertiser interface for managing SHIP and SLAP advertisements using a Ninja.
11
+ */
12
+ export class LegacyNinjaAdvertiser {
13
+ privateKey;
14
+ dojoURL;
15
+ hostingDomain;
16
+ ninja;
17
+ engine;
18
+ /**
19
+ * Constructs a new NinjaAdvertiser instance.
20
+ * @param privateKey - The private key used for signing transactions.
21
+ * @param dojoURL - The URL of the dojo server for the Ninja.
22
+ * @param hostingDomain - The base server URL for the NinjaAdvertiser.
23
+ */
24
+ constructor(privateKey, dojoURL, hostingDomain) {
25
+ this.privateKey = privateKey;
26
+ this.dojoURL = dojoURL;
27
+ this.hostingDomain = hostingDomain;
28
+ this.ninja = new Ninja({
29
+ privateKey,
30
+ config: {
31
+ dojoURL
32
+ }
33
+ });
34
+ }
35
+ /**
36
+ * Sets the Engine instance to be used by this NinjaAdvertiser. This method allows for late
37
+ * binding of the Engine, thus avoiding circular dependencies during instantiation. The Engine
38
+ * provides necessary context with the relevant topic managers and lookup services,
39
+ * as well as the lookup function used for querying advertisements.
40
+ *
41
+ * @param engine The Engine instance to be associated with this NinjaAdvertiser. The Engine should
42
+ * be fully initialized before being passed to this method to ensure all functionalities are available.
43
+ */
44
+ setLookupEngine(engine) {
45
+ this.engine = engine;
46
+ }
47
+ /**
48
+ * Utility function to create multiple advertisements in a single transaction.
49
+ * @param privateKey The private key used to sign the transaction.
50
+ * @param adsData Array of advertisement details.
51
+ * @param ninja Ninja instance for transaction processing.
52
+ * @param note A note attached to the transaction.
53
+ * @returns A promise that resolves to an array of TaggedBEEF objects.
54
+ * @throws Will throw an error if the locking key is invalid.
55
+ */
56
+ async createAdvertisements(adsData) {
57
+ const identityKey = PublicKey.fromPrivateKey(new PrivateKey(this.privateKey, 'hex')).toString();
58
+ const outputs = await Promise.all(adsData.map(async (ad) => {
59
+ // Derive a locking private key using BRC-42 derivation scheme
60
+ const derivedPrivateKey = getPaymentPrivateKey({
61
+ recipientPrivateKey: this.privateKey,
62
+ senderPublicKey: identityKey,
63
+ invoiceNumber: `2-${ad.protocol}-1`,
64
+ returnType: 'hex'
65
+ });
66
+ const lockingScript = await pushdrop.create({
67
+ fields: [
68
+ Buffer.from(ad.protocol),
69
+ Buffer.from(identityKey, 'hex'),
70
+ Buffer.from(this.hostingDomain),
71
+ Buffer.from(ad.topicOrServiceName)
72
+ ],
73
+ key: derivedPrivateKey
74
+ });
75
+ return {
76
+ satoshis: AD_TOKEN_VALUE,
77
+ script: lockingScript
78
+ };
79
+ }));
80
+ const tx = await this.ninja.getTransactionWithOutputs({
81
+ outputs,
82
+ note: 'SHIP/SLAP Advertisement Issuance',
83
+ autoProcess: true
84
+ });
85
+ const beef = toBEEFfromEnvelope({
86
+ rawTx: tx.rawTx,
87
+ inputs: tx.inputs,
88
+ txid: tx.txid
89
+ }).beef;
90
+ return {
91
+ beef,
92
+ topics: [...new Set(adsData.map(ad => ad.protocol === 'SHIP' ? 'tm_ship' : 'tm_slap'))]
93
+ };
94
+ }
95
+ /**
96
+ * Finds all SHIP advertisements for a given topic.
97
+ * @param topic - The topic name to search for.
98
+ * @returns A promise that resolves to an array of SHIP advertisements.
99
+ */
100
+ async findAllAdvertisements(protocol) {
101
+ if (this.engine === undefined) {
102
+ throw new Error('Advertiser must be configured with an overlay services engine for advertisement lookup.');
103
+ }
104
+ const advertisements = [];
105
+ const lookupAnswer = await this.engine.lookup({
106
+ service: protocol === 'SHIP' ? 'ls_ship' : 'ls_slap',
107
+ query: 'findAll'
108
+ });
109
+ // Lookup will currently always return type output-list
110
+ if (lookupAnswer.type === 'output-list') {
111
+ lookupAnswer.outputs.forEach(output => {
112
+ try {
113
+ // Parse out the advertisements using the provided parser
114
+ const tx = Transaction.fromBEEF(output.beef);
115
+ const advertisement = this.parseAdvertisement(tx.outputs[output.outputIndex].lockingScript);
116
+ if (advertisement !== undefined && advertisement !== null && advertisement.protocol === protocol) {
117
+ advertisements.push({
118
+ ...advertisement,
119
+ beef: output.beef,
120
+ outputIndex: output.outputIndex
121
+ });
122
+ }
123
+ }
124
+ catch (error) {
125
+ console.error('Failed to parse advertisement output:', error);
126
+ }
127
+ });
128
+ }
129
+ return advertisements;
130
+ }
131
+ /**
132
+ * Revokes an existing advertisement.
133
+ * @param advertisements - The advertisements to revoke, either SHIP or SLAP.
134
+ * @returns A promise that resolves to the revoked advertisement as TaggedBEEF.
135
+ */
136
+ async revokeAdvertisements(advertisements) {
137
+ if (advertisements.length === 0) {
138
+ throw new Error('Must provide advertisements to revoke!');
139
+ }
140
+ const inputsByTxid = {};
141
+ for (const advertisement of advertisements) {
142
+ if (advertisement.beef === undefined || advertisement.outputIndex === undefined) {
143
+ throw new Error('Advertisement to revoke must contain tagged beef!');
144
+ }
145
+ // Parse the transaction and UTXO to spend
146
+ const advertisementTx = Transaction.fromBEEF(advertisement.beef);
147
+ const adTxid = advertisementTx.id('hex');
148
+ const outputToRedeem = advertisementTx.outputs[advertisement.outputIndex];
149
+ const identityKey = PublicKey.fromPrivateKey(new PrivateKey(this.privateKey, 'hex')).toString();
150
+ // Derive a unlocking private key using BRC-42 derivation scheme
151
+ const derivedPrivateKey = getPaymentPrivateKey({
152
+ recipientPrivateKey: this.privateKey,
153
+ senderPublicKey: identityKey,
154
+ invoiceNumber: `2-${advertisement.protocol}-1`,
155
+ returnType: 'hex'
156
+ });
157
+ const unlockingScript = await pushdrop.redeem({
158
+ key: derivedPrivateKey,
159
+ prevTxId: adTxid,
160
+ outputIndex: advertisement.outputIndex,
161
+ lockingScript: outputToRedeem.lockingScript.toHex(),
162
+ outputAmount: outputToRedeem.satoshis
163
+ });
164
+ const constructedRedeem = {
165
+ index: advertisement.outputIndex,
166
+ unlockingScript
167
+ };
168
+ // Group outputs by their transaction ID
169
+ if (inputsByTxid[adTxid] === undefined) {
170
+ inputsByTxid[adTxid] = {
171
+ ...toEnvelopeFromBEEF(advertisementTx),
172
+ rawTx: advertisementTx.toHex(),
173
+ outputsToRedeem: [constructedRedeem]
174
+ };
175
+ }
176
+ else {
177
+ inputsByTxid[adTxid].outputsToRedeem.push(constructedRedeem);
178
+ }
179
+ }
180
+ // Create a new transaction that spends the SHIP or SLAP advertisement issuance token
181
+ const revokeTx = await this.ninja.getTransactionWithOutputs({
182
+ inputs: inputsByTxid,
183
+ outputs: [],
184
+ labels: [],
185
+ note: 'Revoked SHIP/SLAP advertisements',
186
+ autoProcess: true
187
+ });
188
+ const beef = toBEEFfromEnvelope({
189
+ rawTx: revokeTx.rawTx,
190
+ inputs: revokeTx.inputs,
191
+ txid: revokeTx.txid
192
+ }).beef;
193
+ return {
194
+ beef,
195
+ topics: [...new Set(advertisements.map(ad => ad.protocol === 'SHIP' ? 'tm_ship' : 'tm_slap'))]
196
+ };
197
+ }
198
+ /**
199
+ * Parses an advertisement from the provided output script.
200
+ * @param outputScript - The output script to parse.
201
+ * @returns An Advertisement object if the script matches the expected format, otherwise throws an error.
202
+ */
203
+ parseAdvertisement(outputScript) {
204
+ try {
205
+ const result = pushdrop.decode({
206
+ script: outputScript.toHex(),
207
+ fieldFormat: 'buffer'
208
+ });
209
+ if (result.fields.length < 4) {
210
+ throw new Error('Invalid SHIP/SLAP advertisement!');
211
+ }
212
+ const protocol = result.fields[0].toString();
213
+ if (protocol !== 'SHIP' && protocol !== 'SLAP') {
214
+ throw new Error('Invalid protocol type!');
215
+ }
216
+ const identityKey = result.fields[1].toString('hex');
217
+ const domain = result.fields[2].toString();
218
+ const topicOrService = result.fields[3].toString();
219
+ // Construct a unified Advertisement object
220
+ return {
221
+ protocol: protocol,
222
+ identityKey,
223
+ domain,
224
+ topicOrService
225
+ };
226
+ }
227
+ catch (error) {
228
+ console.error('Error parsing advertisement:', error);
229
+ throw new Error('Error parsing advertisement!');
230
+ }
231
+ }
232
+ }
233
+ //# sourceMappingURL=LegacyNinjaAdvertiser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LegacyNinjaAdvertiser.js","sourceRoot":"","sources":["../../../src/LegacyNinjaAdvertiser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ import * as path from 'path';
4
+ const execPromise = promisify(exec);
5
+ const docs = [
6
+ {
7
+ input: './src/SHIP/SHIPTopicManager.ts',
8
+ output: './docs/SHIP/ship-topic-manager.md'
9
+ },
10
+ {
11
+ input: './src/SHIP/SHIPLookupService.ts',
12
+ output: './docs/SHIP/ship-lookup-service.md'
13
+ },
14
+ {
15
+ input: './src/SHIP/SHIPStorage.ts',
16
+ output: './docs/SHIP/ship-storage.md'
17
+ },
18
+ {
19
+ input: './src/SLAP/SLAPTopicManager.ts',
20
+ output: './docs/SLAP/slap-topic-manager.md'
21
+ },
22
+ {
23
+ input: './src/SLAP/SLAPLookupService.ts',
24
+ output: './docs/SLAP/slap-lookup-service.md'
25
+ },
26
+ {
27
+ input: './src/SLAP/SLAPStorage.ts',
28
+ output: './docs/SLAP/slap-storage.md'
29
+ }
30
+ ];
31
+ // Helper function for generating updated documentation
32
+ const generateDocs = async () => {
33
+ for (const doc of docs) {
34
+ const command = `npx ts2md --inputFilename ${path.resolve(doc.input)} --outputFilename ${path.resolve(doc.output)} --firstHeadingLevel 2 --noTitle true --readmeMerge true`;
35
+ try {
36
+ const { stdout, stderr } = await execPromise(command);
37
+ console.log(`stdout: ${stdout}`);
38
+ console.error(`stderr: ${stderr}`);
39
+ }
40
+ catch (error) {
41
+ console.error(`Error generating documentation for ${doc.input}:`, error);
42
+ }
43
+ }
44
+ };
45
+ generateDocs().then(() => console.log('Documentation generation complete')).catch(error => console.error('Error:', error));
46
+ //# sourceMappingURL=generateDocs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateDocs.js","sourceRoot":"","sources":["../../../../src/utils/generateDocs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAA;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAA;AAChC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAE5B,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;AAOnC,MAAM,IAAI,GAAgB;IACxB;QACE,KAAK,EAAE,gCAAgC;QACvC,MAAM,EAAE,mCAAmC;KAC5C;IACD;QACE,KAAK,EAAE,iCAAiC;QACxC,MAAM,EAAE,oCAAoC;KAC7C;IACD;QACE,KAAK,EAAE,2BAA2B;QAClC,MAAM,EAAE,6BAA6B;KACtC;IACD;QACE,KAAK,EAAE,gCAAgC;QACvC,MAAM,EAAE,mCAAmC;KAC5C;IACD;QACE,KAAK,EAAE,iCAAiC;QACxC,MAAM,EAAE,oCAAoC;KAC7C;IACD;QACE,KAAK,EAAE,2BAA2B;QAClC,MAAM,EAAE,6BAA6B;KACtC;CACF,CAAA;AAED,uDAAuD;AACvD,MAAM,YAAY,GAAG,KAAK,IAAI,EAAE;IAC9B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,6BAA6B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,qBAAqB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,0DAA0D,CAAA;QAC3K,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC,OAAO,CAAC,CAAA;YACrD,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,EAAE,CAAC,CAAA;YAChC,OAAO,CAAC,KAAK,CAAC,WAAW,MAAM,EAAE,CAAC,CAAA;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,sCAAsC,GAAG,CAAC,KAAK,GAAG,EAAE,KAAK,CAAC,CAAA;QAC1E,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,YAAY,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAA"}
@@ -0,0 +1,20 @@
1
+ import { promises as fs } from 'fs';
2
+ import { resolve, dirname } from 'path';
3
+ /**
4
+ * Returns documentation specific to the provided filename
5
+ * @param {string} filePath - The path of the markdown file
6
+ * @returns A promise that resolves to the documentation string
7
+ */
8
+ async function getDocumentation(filePath) {
9
+ try {
10
+ const resolvedPath = resolve(dirname(require.resolve('@bsv/overlay-discovery-services')), '../../', filePath);
11
+ const data = await fs.readFile(resolvedPath, 'utf-8');
12
+ return data;
13
+ }
14
+ catch (error) {
15
+ console.error('Error reading documentation file:', error);
16
+ throw new Error('Failed to read documentation file');
17
+ }
18
+ }
19
+ export { getDocumentation };
20
+ //# sourceMappingURL=getDocumentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"getDocumentation.js","sourceRoot":"","sources":["../../../../src/utils/getDocumentation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AACvC;;;;GAIG;AACH,KAAK,UAAU,gBAAgB,CAAC,QAAgB;IAC9C,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;QAC7G,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;QACrD,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAA;QACzD,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;IACtD,CAAC;AACH,CAAC;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAA"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Validates if the provided domain name is valid.
3
+ * @param domain - The domain name to validate.
4
+ * @returns True if the domain name is valid, false otherwise.
5
+ */
6
+ export const isValidDomain = (domain) => {
7
+ // Simple regex to validate domain name
8
+ const domainRegex = /^(https?:\/\/)?((([a-zA-Z0-9-]+)\.)+([a-zA-Z]{2,})|localhost(:[0-9]+))(\/.*)?$/;
9
+ return domainRegex.test(domain);
10
+ };
11
+ //# sourceMappingURL=isValidDomain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isValidDomain.js","sourceRoot":"","sources":["../../../../src/utils/isValidDomain.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAc,EAAW,EAAE;IACvD,uCAAuC;IACvC,MAAM,WAAW,GAAG,gFAAgF,CAAA;IACpG,OAAO,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AACjC,CAAC,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Validates if the provided service name is valid based on BRC-87 guidelines.
3
+ * @param service - The service name to validate.
4
+ * @returns True if the service name is valid, false otherwise.
5
+ */
6
+ export const isValidServiceName = (service) => {
7
+ const serviceRegex = /^(?!_)(?!.*__)[a-z_]{1,50}(?<!_)$/;
8
+ return serviceRegex.test(service);
9
+ };
10
+ //# sourceMappingURL=isValidServiceName.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isValidServiceName.js","sourceRoot":"","sources":["../../../../src/utils/isValidServiceName.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAe,EAAW,EAAE;IAC7D,MAAM,YAAY,GAAG,mCAAmC,CAAA;IACxD,OAAO,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AACnC,CAAC,CAAA"}
@@ -0,0 +1,18 @@
1
+ import { PublicKey, Signature } from '@bsv/sdk';
2
+ /**
3
+ * Verifies the BRC-48 locking key and the signature.
4
+ * @private
5
+ * @param identityKey - The BRC-31 identity key of the advertiser.
6
+ * @param lockingPublicKey - The public key used in the output's locking script.
7
+ * @param fields - The fields of the token.
8
+ * @param signature - The signature over the token fields.
9
+ * @param protocolId - The protocol ID (e.g., 'SHIP' or 'SLAP').
10
+ * @throws Will throw an error if the locking key or signature is invalid.
11
+ */
12
+ export const verifyToken = (identityKey, lockingPublicKey, fields, signature) => {
13
+ const pubKey = PublicKey.fromString(lockingPublicKey);
14
+ const hasValidSignature = pubKey.verify(Array.from(Buffer.concat(fields)), Signature.fromDER(signature, 'hex'));
15
+ if (!hasValidSignature)
16
+ throw new Error('Invalid signature!');
17
+ };
18
+ //# sourceMappingURL=verifyToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verifyToken.js","sourceRoot":"","sources":["../../../../src/utils/verifyToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAE/C;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,WAAmB,EACnB,gBAAwB,EACxB,MAAgB,EAChB,SAAiB,EACX,EAAE;IACR,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAA;IACrD,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CACrC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EACjC,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CACpC,CAAA;IAED,IAAI,CAAC,iBAAiB;QAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAA;AAC/D,CAAC,CAAA"}