@bsv/overlay 0.1.0-alpha.1 → 0.1.0-alpha.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 (51) hide show
  1. package/dist/cjs/mod.js +5 -14
  2. package/dist/cjs/mod.js.map +1 -1
  3. package/dist/cjs/package.json +2 -2
  4. package/dist/cjs/src/Engine.js +110 -43
  5. package/dist/cjs/src/Engine.js.map +1 -1
  6. package/dist/cjs/src/storage/knex/KnexStorage.js +25 -3
  7. package/dist/cjs/src/storage/knex/KnexStorage.js.map +1 -1
  8. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  9. package/dist/esm/mod.js +2 -13
  10. package/dist/esm/mod.js.map +1 -1
  11. package/dist/esm/src/Engine.js +110 -43
  12. package/dist/esm/src/Engine.js.map +1 -1
  13. package/dist/esm/src/storage/knex/KnexStorage.js +24 -3
  14. package/dist/esm/src/storage/knex/KnexStorage.js.map +1 -1
  15. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  16. package/dist/types/mod.d.ts +12 -12
  17. package/dist/types/mod.d.ts.map +1 -1
  18. package/dist/types/src/AdmittanceInstructions.d.ts +2 -2
  19. package/dist/types/src/AdmittanceInstructions.d.ts.map +1 -1
  20. package/dist/types/src/Engine.d.ts +46 -26
  21. package/dist/types/src/Engine.d.ts.map +1 -1
  22. package/dist/types/src/LookupAnswer.d.ts.map +1 -1
  23. package/dist/types/src/LookupFormula.d.ts +5 -5
  24. package/dist/types/src/LookupFormula.d.ts.map +1 -1
  25. package/dist/types/src/LookupQuestion.d.ts.map +1 -1
  26. package/dist/types/src/LookupService.d.ts +32 -20
  27. package/dist/types/src/LookupService.d.ts.map +1 -1
  28. package/dist/types/src/Output.d.ts +4 -4
  29. package/dist/types/src/Output.d.ts.map +1 -1
  30. package/dist/types/src/STEAK.d.ts +1 -1
  31. package/dist/types/src/TopicManager.d.ts +5 -5
  32. package/dist/types/src/TopicManager.d.ts.map +1 -1
  33. package/dist/types/src/storage/Storage.d.ts +47 -34
  34. package/dist/types/src/storage/Storage.d.ts.map +1 -1
  35. package/dist/types/src/storage/knex/KnexStorage.d.ts +6 -4
  36. package/dist/types/src/storage/knex/KnexStorage.d.ts.map +1 -1
  37. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  38. package/mod.ts +12 -12
  39. package/package.json +2 -2
  40. package/src/AdmittanceInstructions.ts +8 -8
  41. package/src/Engine.ts +458 -383
  42. package/src/LookupAnswer.ts +7 -7
  43. package/src/LookupFormula.ts +21 -21
  44. package/src/LookupQuestion.ts +9 -9
  45. package/src/LookupService.ts +54 -36
  46. package/src/Output.ts +22 -22
  47. package/src/STEAK.ts +1 -1
  48. package/src/TopicManager.ts +21 -15
  49. package/src/__tests/Engine.test.ts +6 -4
  50. package/src/storage/Storage.ts +49 -34
  51. package/src/storage/knex/KnexStorage.ts +101 -76
@@ -3,12 +3,12 @@
3
3
  * It may comprise either an output list or a freeform response from the Lookup Service.
4
4
  */
5
5
  export type LookupAnswer = {
6
- type: 'output-list'
7
- outputs: Array<{
8
- beef: number[]
9
- outputIndex: number
10
- }>
6
+ type: 'output-list'
7
+ outputs: Array<{
8
+ beef: number[]
9
+ outputIndex: number
10
+ }>
11
11
  } | {
12
- type: 'freeform',
13
- result: unknown
12
+ type: 'freeform'
13
+ result: unknown
14
14
  }
@@ -1,26 +1,26 @@
1
1
  /**
2
2
  * The formula that will be used by the Overlay Services Engine to compute the Lookup Answer. Can be returned by Lookup Services in response to a Lookup Question.
3
3
  */
4
- export type LookupFormula = {
5
- /**
6
- * TXID of the transaction where an output responsive to the Lookup Question resides.
7
- */
8
- txid: string,
4
+ export type LookupFormula = Array<{
5
+ /**
6
+ * TXID of the transaction where an output responsive to the Lookup Question resides.
7
+ */
8
+ txid: string
9
9
 
10
- /**
11
- * Index of the transaction output responsive to the Lookup Question.
12
- */
13
- outputIndex: number,
10
+ /**
11
+ * Index of the transaction output responsive to the Lookup Question.
12
+ */
13
+ outputIndex: number
14
14
 
15
- /**
16
- * Decides what history to incorporate into the Lookup Answer.
17
- *
18
- * Optionally directs the Overlay Services Engine as to the historical context (preceeding outputs) to include as part of the Lookup Answer.
19
- * - If a number, denotes how many previous spends (in terms of chain depth) the Engine should include with the Answer.
20
- * - If a decider function, accepts a BEEF-formatted transaction, an output index and the current depth (relative to the top-level respnosive UTXO) as parameters.
21
- * The function returns a promise for a boolean indicating whether the output should be incorporated into the Lookup Answer.
22
- * If so, the function will be called again for transactions that preceeded the one provided, ultimately allowing the complete shape of the responsive spend history to be described.
23
- * If not provided, no historical information will be included with the Lookup Answer, except that which may incidentally be required to fully anchor the Lookup Answer to the blockchain.
24
- */
25
- history?: ((beef: number[], outputIndex: number, currentDepth: number) => Promise<boolean>) | number
26
- }[]
15
+ /**
16
+ * Decides what history to incorporate into the Lookup Answer.
17
+ *
18
+ * Optionally directs the Overlay Services Engine as to the historical context (preceding outputs) to include as part of the Lookup Answer.
19
+ * - If a number, denotes how many previous spends (in terms of chain depth) the Engine should include with the Answer.
20
+ * - If a decider function, accepts a BEEF-formatted transaction, an output index and the current depth (relative to the top-level responsive UTXO) as parameters.
21
+ * The function returns a promise for a boolean indicating whether the output should be incorporated into the Lookup Answer.
22
+ * If so, the function will be called again for transactions that preceded the one provided, ultimately allowing the complete shape of the responsive spend history to be described.
23
+ * If not provided, no historical information will be included with the Lookup Answer, except that which may incidentally be required to fully anchor the Lookup Answer to the blockchain.
24
+ */
25
+ history?: ((beef: number[], outputIndex: number, currentDepth: number) => Promise<boolean>) | number
26
+ }>
@@ -2,14 +2,14 @@
2
2
  * The question asked to the Overlay Services Engine when a consumer of state wishes to look up information.
3
3
  */
4
4
  export type LookupQuestion = {
5
- /**
6
- * The identifier for a Lookup Service which the person asking the question wishes to use.
7
- */
8
- service: string
5
+ /**
6
+ * The identifier for a Lookup Service which the person asking the question wishes to use.
7
+ */
8
+ service: string
9
9
 
10
- /**
11
- * The query which will be forwarded to the Lookup Service.
12
- * Its type depends on that prescribed by the Lookup Service employed.
13
- */
14
- query: unknown
10
+ /**
11
+ * The query which will be forwarded to the Lookup Service.
12
+ * Its type depends on that prescribed by the Lookup Service employed.
13
+ */
14
+ query: unknown
15
15
  }
@@ -6,47 +6,65 @@ import { Script } from '@bsv/sdk'
6
6
  /**
7
7
  * Defines a Lookup Service interface to be implemented for specific use-cases
8
8
  */
9
- export default interface LookupService {
9
+ export interface LookupService {
10
10
 
11
- /**
12
- * Process the event when a new UTXO is let into a topic
13
- * @param txid
14
- * @param outputIndex
15
- * @param outputScript
16
- * @param topic
17
- */
18
- outputAdded?(txid: string, outputIndex: number, outputScript: Script, topic: string): Promise<void>
11
+ /**
12
+ * Process the event when a new UTXO is let into a topic
13
+ * @param txid - The transaction ID (TXID) of the transaction where the new UTXO resides.
14
+ * @param outputIndex - The index of the transaction output (UTXO) within the transaction.
15
+ * @param outputScript - The script associated with the transaction output.
16
+ * @param topic - The topic to which the new UTXO is being added.
17
+ * @returns A promise that resolves when the processing of the new UTXO is complete.
18
+ */
19
+ outputAdded?: (txid: string, outputIndex: number, outputScript: Script, topic: string) => Promise<void>
19
20
 
20
- /**
21
- * Process the spend event for a UTXO
22
- * @param txid
23
- * @param outputIndex
24
- * @param topic
25
- */
26
- outputSpent?(txid: string, outputIndex: number, topic: string): Promise<void>
21
+ /**
22
+ * Processes the spend event for a UTXO.
23
+ *
24
+ * @param txid - The transaction ID of the spent UTXO.
25
+ * @param outputIndex - The index of the transaction output that was spent.
26
+ * @param topic - The topic from which the UTXO was spent.
27
+ *
28
+ * @returns A promise that resolves when processing is complete.
29
+ */
30
+ outputSpent?: (txid: string, outputIndex: number, topic: string) => Promise<void>
27
31
 
28
- /**
29
- * Process the deletion event for a UTXO
30
- * @param txid
31
- * @param outputIndex
32
- * @param topic
32
+ /**
33
+ * Processes the deletion event for a UTXO.
34
+ *
35
+ * @param txid - The transaction ID of the deleted UTXO.
36
+ * @param outputIndex - The index of the transaction output that was deleted.
37
+ * @param topic - The topic from which the UTXO was deleted.
38
+ *
39
+ * @returns A promise that resolves when processing is complete.
33
40
  */
34
- outputDeleted?(txid: string, outputIndex: number, topic: string): Promise<void>
41
+ outputDeleted?: (txid: string, outputIndex: number, topic: string) => Promise<void>
35
42
 
36
- /**
37
- * Queries the lookup service for information
38
- * @param question — The question to be answered by the lookup service
39
- * @returns — The Lookup Answer or Lookup Formula used to answer the question
40
- */
41
- lookup(question: LookupQuestion): Promise<LookupAnswer | LookupFormula>
43
+ /**
44
+ * Queries the lookup service for information
45
+ * @param question — The question to be answered by the lookup service
46
+ * @returns — The Lookup Answer or Lookup Formula used to answer the question
47
+ */
48
+ lookup: (question: LookupQuestion) => Promise<LookupAnswer | LookupFormula>
42
49
 
43
- /**
44
- * Returns a Markdown-formatted documentation string for the lookup service.
45
- */
46
- getDocumentation(): Promise<string>
50
+ /**
51
+ * Returns a Markdown-formatted documentation string for the lookup service.
52
+ *
53
+ * @returns A promise that resolves to a documentation string.
54
+ */
55
+ getDocumentation: () => Promise<string>
47
56
 
48
- /**
49
- * Returns a metadata object that can be used to identify the lookup service.
50
- */
51
- getMetaData(): Promise<{ name: string, shortDescription: string, iconURL?: string, version?: string, informationURL?: string }>
57
+ /**
58
+ * Returns a metadata object that can be used to identify the lookup service.
59
+ *
60
+ * @returns A promise that resolves to a metadata object containing the name, short description,
61
+ * and optional properties such as icon URL, version, and information URL.
62
+ */
63
+ getMetaData: () => Promise<{
64
+ name: string
65
+ shortDescription: string
66
+ iconURL?: string
67
+ version?: string
68
+ informationURL?: string
69
+ }>
52
70
  }
package/src/Output.ts CHANGED
@@ -2,28 +2,28 @@
2
2
  * Represents an output to be tracked by the Overlay Services Engine
3
3
  */
4
4
  export type Output = {
5
- /** TXID of the output */
5
+ /** TXID of the output */
6
+ txid: string
7
+ /** index of the output */
8
+ outputIndex: number
9
+ /** script of the output */
10
+ outputScript: number[]
11
+ /** number of satoshis in the output */
12
+ satoshis: number
13
+ /** topic to which the output belongs */
14
+ topic: string
15
+ /** Whether the output is spent */
16
+ spent: boolean
17
+ /** The transaction data for the output */
18
+ beef: number[]
19
+ /** Outputs consumed by the transaction associated with the output */
20
+ outputsConsumed: Array<{
6
21
  txid: string
7
- /** index of the output */
8
22
  outputIndex: number
9
- /** script of the output */
10
- outputScript: number[]
11
- /** number of satoshis in the output */
12
- satoshis: number
13
- /** topic to which the output belongs */
14
- topic: string
15
- /** Whether the output is spent */
16
- spent: boolean
17
- /** The transaction data for the output */
18
- beef: number[]
19
- /** Outputs consumed by the transaction associated with the output */
20
- outputsConsumed: {
21
- txid: string
22
- outputIndex: number
23
- }[]
24
- /** Outputs consuming this output */
25
- consumedBy: {
26
- txid: string
27
- outputIndex: number
28
- }[]
23
+ }>
24
+ /** Outputs consuming this output */
25
+ consumedBy: Array<{
26
+ txid: string
27
+ outputIndex: number
28
+ }>
29
29
  }
package/src/STEAK.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { AdmittanceInstructions } from "./AdmittanceInstructions.js"
1
+ import { AdmittanceInstructions } from './AdmittanceInstructions.js'
2
2
 
3
3
  /**
4
4
  * Submitted Transaction Execution AcKnowledgment
@@ -3,21 +3,27 @@ import { AdmittanceInstructions } from './AdmittanceInstructions.js'
3
3
  /**
4
4
  * Defines a Topic Manager interface that can be implemented for specific use-cases
5
5
  */
6
- export default interface TopicManager {
7
- /**
8
- * Returns instructions that denote which outputs from the provided transaction to admit into the topic, and which previous coins should be retained.
9
- * Accepts the transaction in BEEF format and an array of those input indicies which spend previously-admitted outputs from the same topic.
10
- * The transaction's BEEF structure will always contain the transactions associated with previous coins for reference (if any), regardless of whether the current transaction was directly proven.
11
- */
12
- identifyAdmissibleOutputs(beef: number[], previousCoins: number[]): Promise<AdmittanceInstructions>
6
+ export interface TopicManager {
7
+ /**
8
+ * Returns instructions that denote which outputs from the provided transaction to admit into the topic, and which previous coins should be retained.
9
+ * Accepts the transaction in BEEF format and an array of those input indices which spend previously-admitted outputs from the same topic.
10
+ * The transaction's BEEF structure will always contain the transactions associated with previous coins for reference (if any), regardless of whether the current transaction was directly proven.
11
+ */
12
+ identifyAdmissibleOutputs: (beef: number[], previousCoins: number[]) => Promise<AdmittanceInstructions>
13
13
 
14
- /**
15
- * Returns a Markdown-formatted documentation string for the topic manager.
16
- */
17
- getDocumentation(): Promise<string>
14
+ /**
15
+ * Returns a Markdown-formatted documentation string for the topic manager.
16
+ */
17
+ getDocumentation: () => Promise<string>
18
18
 
19
- /**
20
- * Returns a metadata object that can be used to identify the topic manager.
21
- */
22
- getMetaData(): Promise<{ name: string, shortDescription: string, iconURL?: string, version?: string, informationURL?: string }>
19
+ /**
20
+ * Returns a metadata object that can be used to identify the topic manager.
21
+ */
22
+ getMetaData: () => Promise<{
23
+ name: string
24
+ shortDescription: string
25
+ iconURL?: string
26
+ version?: string
27
+ informationURL?: string
28
+ }>
23
29
  }
@@ -1,8 +1,8 @@
1
- import Engine from '../Engine'
2
- import LookupService from '../LookupService'
3
- import TopicManager from '../TopicManager'
1
+ import { Engine } from '../Engine'
2
+ import { LookupService } from '../LookupService'
3
+ import { TopicManager } from '../TopicManager'
4
4
  import { AdmittanceInstructions } from '../AdmittanceInstructions'
5
- import Storage from '../storage/Storage'
5
+ import { Storage } from '../storage/Storage'
6
6
  import { Transaction } from '@bsv/sdk'
7
7
  import { Output } from '../Output'
8
8
 
@@ -56,8 +56,10 @@ describe('BSV Overlay Services Engine', () => {
56
56
  insertAppliedTransaction: jest.fn(),
57
57
  insertOutput: jest.fn(),
58
58
  findOutput: jest.fn(async () => null),
59
+ findOutputsForTransaction: jest.fn(async () => []),
59
60
  markUTXOAsSpent: jest.fn(),
60
61
  updateConsumedBy: jest.fn(),
62
+ updateOutputBeef: jest.fn(),
61
63
  deleteOutput: jest.fn()
62
64
  }
63
65
  })
@@ -1,7 +1,7 @@
1
1
  import type { Output } from '../Output.js'
2
2
 
3
3
  /**
4
- * Representa a transaction that has been applied to a topic.
4
+ * Represents a transaction that has been applied to a topic.
5
5
  */
6
6
  interface AppliedTransaction {
7
7
  /** TXID of the applied transaction */
@@ -13,60 +13,75 @@ interface AppliedTransaction {
13
13
  /**
14
14
  * Defines the Storage Engine interface used internally by the Overlay Services Engine.
15
15
  */
16
- export default interface Storage {
16
+ export interface Storage {
17
17
  /**
18
- * Adds a new output to storage
19
- * @param utxo — The output to add
20
- */
18
+ * Adds a new output to storage
19
+ * @param utxo — The output to add
20
+ */
21
21
  insertOutput: (utxo: Output) => Promise<void>
22
22
 
23
23
  /**
24
- * Finds an output from storage
25
- * @param txid — TXID of hte output to find
26
- * @param outputIndex — Output index for the output to find
27
- * @param topic — The topic in which the output is stored
28
- * @param spent — Whether the output must be spent to be returned
29
- */
24
+ * Finds an output from storage
25
+ * @param txid — TXID of hte output to find
26
+ * @param outputIndex — Output index for the output to find
27
+ * @param topic — The topic in which the output is stored
28
+ * @param spent — Whether the output must be spent to be returned
29
+ */
30
30
  findOutput: (txid: string, outputIndex: number, topic?: string, spent?: boolean) => Promise<Output | null>
31
31
 
32
32
  /**
33
- * Deletes an output from storage
34
- * @param txid — The TXID of the output to delete
35
- * @param outputIndex — The index of the output to delete
36
- * @param topic — The topic where the output should be deleted
37
- */
33
+ * Finds outputs with a matching transaction ID from storage
34
+ * @param txid — TXID of the outputs to find
35
+ */
36
+ findOutputsForTransaction: (txid: string) => Promise<Output[]>
37
+
38
+ /**
39
+ * Deletes an output from storage
40
+ * @param txid — The TXID of the output to delete
41
+ * @param outputIndex — The index of the output to delete
42
+ * @param topic — The topic where the output should be deleted
43
+ */
38
44
  deleteOutput: (txid: string, outputIndex: number, topic: string) => Promise<void>
39
45
 
40
46
  /**
41
- * Updates a UTXO as spent
42
- * @param txid — TXID of the output to update
43
- * @param outputIndex — Index of the output to update
44
- * @param topic — Topic in which the output should be updated
45
- */
47
+ * Updates a UTXO as spent
48
+ * @param txid — TXID of the output to update
49
+ * @param outputIndex — Index of the output to update
50
+ * @param topic — Topic in which the output should be updated
51
+ */
46
52
  markUTXOAsSpent: (txid: string, outputIndex: number, topic: string) => Promise<void>
47
53
 
48
54
  /**
49
- * Updates which outputs are consumed by this output
50
- * @param txid — TXID of the output to update
51
- * @param outputIndex — Index of the output to update
52
- * @param topic — Topic in which the output should be updated
53
- * @param consumedBy — The new set of outputs consumed by this output
54
- */
55
+ * Updates which outputs are consumed by this output
56
+ * @param txid — TXID of the output to update
57
+ * @param outputIndex — Index of the output to update
58
+ * @param topic — Topic in which the output should be updated
59
+ * @param consumedBy — The new set of outputs consumed by this output
60
+ */
55
61
  updateConsumedBy: (txid: string, outputIndex: number, topic: string, consumedBy: Array<{
56
62
  txid: string
57
63
  outputIndex: number
58
64
  }>) => Promise<void>
59
65
 
60
66
  /**
61
- * Inserts record of the applied transaction
62
- * @param tx — The transaction to insert
63
- */
67
+ * Updates the beef data on an output
68
+ * @param txid — TXID of the output to update
69
+ * @param outputIndex — Index of the output to update
70
+ * @param topic — Topic in which the output should be updated
71
+ * @param beef - BEEF data to update
72
+ */
73
+ updateOutputBeef: (txid: string, outputIndex: number, topic: string, beef: number[]) => Promise<void>
74
+
75
+ /**
76
+ * Inserts record of the applied transaction
77
+ * @param tx — The transaction to insert
78
+ */
64
79
  insertAppliedTransaction: (tx: AppliedTransaction) => Promise<void>
65
80
 
66
81
  /**
67
- * Checks if a duplicate transaction exists
68
- * @param tx — Transaction to check
69
- * @returns Whether the transaction is already applied
70
- */
82
+ * Checks if a duplicate transaction exists
83
+ * @param tx — Transaction to check
84
+ * @returns Whether the transaction is already applied
85
+ */
71
86
  doesAppliedTransactionExist: (tx: AppliedTransaction) => Promise<boolean>
72
87
  }
@@ -1,90 +1,115 @@
1
- import Storage from '../Storage.js'
1
+ import { Storage } from '../Storage.js'
2
2
  import { Knex } from 'knex'
3
3
  import type { Output } from '../../Output.js'
4
4
 
5
- export default class KnexStorage implements Storage {
6
- knex: Knex
5
+ export class KnexStorage implements Storage {
6
+ knex: Knex
7
7
 
8
- constructor(knex: Knex) {
9
- this.knex = knex
10
- }
8
+ constructor(knex: Knex) {
9
+ this.knex = knex
10
+ }
11
11
 
12
- async findOutput(txid: string, outputIndex: number, topic?: string, spent?: boolean): Promise<Output | null> {
13
- const search: {
14
- txid: string,
15
- outputIndex: number,
16
- topic?: string,
17
- spent?: boolean
18
- } = {
19
- txid,
20
- outputIndex
21
- }
22
- if (topic !== undefined) search.topic = topic
23
- if (spent !== undefined) search.spent = spent
24
- const [output] = await this.knex('outputs').where(search).select(
25
- 'txid', 'outputIndex', 'outputScript', 'topic', 'satoshis', 'beef', 'outputsConsumed', 'spent', 'consumedBy'
26
- )
27
- if (!output) {
28
- return null
29
- }
30
- return {
31
- ...output,
32
- outputScript: [...output.outputScript],
33
- beef: [...output.beef],
34
- spent: Boolean(output.spent),
35
- outputsConsumed: JSON.parse(output.outputsConsumed),
36
- consumedBy: JSON.parse(output.consumedBy)
37
- }
12
+ async findOutput(txid: string, outputIndex: number, topic?: string, spent?: boolean): Promise<Output | null> {
13
+ const search: {
14
+ txid: string
15
+ outputIndex: number
16
+ topic?: string
17
+ spent?: boolean
18
+ } = {
19
+ txid,
20
+ outputIndex
38
21
  }
39
-
40
- async deleteOutput(txid: string, outputIndex: number, topic: string): Promise<void> {
41
- await this.knex('outputs').where({
42
- txid, outputIndex, topic
43
- }).del()
22
+ if (topic !== undefined) search.topic = topic
23
+ if (spent !== undefined) search.spent = spent
24
+ const [output] = await this.knex('outputs').where(search).select(
25
+ 'txid', 'outputIndex', 'outputScript', 'topic', 'satoshis', 'beef', 'outputsConsumed', 'spent', 'consumedBy'
26
+ )
27
+ if (output === undefined || output === null) {
28
+ return null
44
29
  }
45
-
46
- async insertOutput(output: Output) {
47
- await this.knex('outputs').insert({
48
- txid: output.txid,
49
- outputIndex: Number(output.outputIndex),
50
- outputScript: Buffer.from(output.outputScript),
51
- topic: output.topic,
52
- satoshis: Number(output.satoshis),
53
- beef: [...output.beef],
54
- outputsConsumed: JSON.stringify(output.outputsConsumed),
55
- consumedBy: JSON.stringify(output.consumedBy),
56
- spent: output.spent
57
- })
30
+ return {
31
+ ...output,
32
+ outputScript: [...output.outputScript],
33
+ beef: [...output.beef],
34
+ spent: Boolean(output.spent),
35
+ outputsConsumed: JSON.parse(output.outputsConsumed),
36
+ consumedBy: JSON.parse(output.consumedBy)
58
37
  }
38
+ }
59
39
 
60
- async markUTXOAsSpent(txid: string, outputIndex: number, topic?: string): Promise<void> {
61
- await this.knex('outputs').where({
62
- txid,
63
- outputIndex,
64
- topic
65
- }).update('spent', true)
40
+ async findOutputsForTransaction(txid: string): Promise<Output[]> {
41
+ const [output] = await this.knex('outputs').where({ txid }).select(
42
+ 'txid', 'outputIndex', 'outputScript', 'topic', 'satoshis', 'beef', 'outputsConsumed', 'spent', 'consumedBy'
43
+ )
44
+ if (output === undefined || output === null) {
45
+ return []
66
46
  }
67
-
68
- async updateConsumedBy(txid: string, outputIndex: number, topic: string, consumedBy: { txid: string, outputIndex: number }[]) {
69
- await this.knex('outputs').where({
70
- txid,
71
- outputIndex,
72
- topic
73
- }).update('consumedBy', consumedBy)
47
+ return {
48
+ ...output,
49
+ outputScript: [...output.outputScript],
50
+ beef: [...output.beef],
51
+ spent: Boolean(output.spent),
52
+ outputsConsumed: JSON.parse(output.outputsConsumed),
53
+ consumedBy: JSON.parse(output.consumedBy)
74
54
  }
55
+ }
75
56
 
76
- async insertAppliedTransaction(tx: { txid: string, topic: string }) {
77
- await this.knex('applied_transactions').insert({
78
- txid: tx.txid,
79
- topic: tx.topic
80
- })
81
- }
57
+ async deleteOutput(txid: string, outputIndex: number, topic: string): Promise<void> {
58
+ await this.knex('outputs').where({
59
+ txid, outputIndex, topic
60
+ }).del()
61
+ }
82
62
 
83
- async doesAppliedTransactionExist(tx: { txid: string, topic: string }): Promise<boolean> {
84
- const appliedTransactions = await this.knex('applied_transactions').where({
85
- txid: tx.txid,
86
- topic: tx.topic
87
- }).select('txid', 'topic')
88
- return appliedTransactions.length > 0
89
- }
63
+ async insertOutput(output: Output): Promise<void> {
64
+ await this.knex('outputs').insert({
65
+ txid: output.txid,
66
+ outputIndex: Number(output.outputIndex),
67
+ outputScript: Buffer.from(output.outputScript),
68
+ topic: output.topic,
69
+ satoshis: Number(output.satoshis),
70
+ beef: Buffer.from(new Uint8Array(output.beef)),
71
+ outputsConsumed: JSON.stringify(output.outputsConsumed),
72
+ consumedBy: JSON.stringify(output.consumedBy),
73
+ spent: output.spent
74
+ })
75
+ }
76
+
77
+ async markUTXOAsSpent(txid: string, outputIndex: number, topic?: string): Promise<void> {
78
+ await this.knex('outputs').where({
79
+ txid,
80
+ outputIndex,
81
+ topic
82
+ }).update('spent', true)
83
+ }
84
+
85
+ async updateConsumedBy(txid: string, outputIndex: number, topic: string, consumedBy: Array<{ txid: string, outputIndex: number }>): Promise<void> {
86
+ await this.knex('outputs').where({
87
+ txid,
88
+ outputIndex,
89
+ topic
90
+ }).update('consumedBy', consumedBy)
91
+ }
92
+
93
+ async updateOutputBeef(txid: string, outputIndex: number, topic: string, beef: number[]): Promise<void> {
94
+ await this.knex('outputs').where({
95
+ txid,
96
+ outputIndex,
97
+ topic
98
+ }).update('beef', beef)
99
+ }
100
+
101
+ async insertAppliedTransaction(tx: { txid: string, topic: string }): Promise<void> {
102
+ await this.knex('applied_transactions').insert({
103
+ txid: tx.txid,
104
+ topic: tx.topic
105
+ })
106
+ }
107
+
108
+ async doesAppliedTransactionExist(tx: { txid: string, topic: string }): Promise<boolean> {
109
+ const appliedTransactions = await this.knex('applied_transactions').where({
110
+ txid: tx.txid,
111
+ topic: tx.topic
112
+ }).select('txid', 'topic')
113
+ return appliedTransactions.length > 0
114
+ }
90
115
  }