• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cameri / nostream / 24609919997

18 Apr 2026 05:23PM UTC coverage: 30.829% (-32.0%) from 62.807%
24609919997

Pull #454

github

web-flow
Merge c337d7af3 into 26bcdd51d
Pull Request #454: fix: OpenNode callback accepts unauthenticated requests

268 of 1385 branches covered (19.35%)

Branch coverage included in aggregate %.

29 of 41 new or added lines in 3 files covered. (70.73%)

976 existing lines in 41 files now uncovered.

1164 of 3260 relevant lines covered (35.71%)

5.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

68.0
/src/utils/transform.ts
1
import { always, applySpec, cond, equals, ifElse, is, isNil, multiply, path, pathSatisfies, pipe, prop, propSatisfies, T } from 'ramda'
1✔
2
import { bech32 } from 'bech32'
1✔
3

4
import { Invoice, InvoiceStatus, InvoiceUnit } from '../@types/invoice'
1✔
5
import { User } from '../@types/user'
6

7
export const toJSON = (input: any) => JSON.stringify(input)
25✔
8

9
export const toBuffer = (input: any) => Buffer.from(input, 'hex')
311✔
10

11
export const fromBuffer = (input: Buffer) => input.toString('hex')
103✔
12

13
export const toBigInt = (input: string | number): bigint => BigInt(input)
1✔
14

15
export const fromBigInt = (input: bigint) => input.toString()
1✔
16

17
const addTime = (ms: number) => (input: Date) => new Date(input.getTime() + ms)
1✔
18

19
export const fromDBInvoice = applySpec<Invoice>({
1✔
20
  id: prop('id') as () => string,
21
  pubkey: pipe(prop('pubkey') as () => Buffer, fromBuffer),
22
  bolt11: prop('bolt11'),
23
  amountRequested: pipe(prop('amount_requested') as () => string, toBigInt),
24
  amountPaid: ifElse(
25
    propSatisfies(isNil, 'amount_paid'),
26
    always(undefined),
27
    pipe(prop('amount_paid') as () => string, toBigInt),
28
  ),
29
  unit: prop('unit'),
30
  status: prop('status'),
31
  description: prop('description'),
32
  confirmedAt: prop('confirmed_at'),
33
  expiresAt: prop('expires_at'),
34
  updatedAt: prop('updated_at'),
35
  createdAt: prop('created_at'),
36
  verifyURL: prop('verify_url'),
37
})
38

39
export const fromDBUser = applySpec<User>({
1✔
40
  pubkey: pipe(prop('pubkey') as () => Buffer, fromBuffer),
41
  isAdmitted: prop('is_admitted'),
42
  isVanished: prop('is_vanished'),
43
  balance: prop('balance'),
44
  createdAt: prop('created_at'),
45
  updatedAt: prop('updated_at'),
46
})
47

48
export const fromBech32 = (input: string) => {
1✔
UNCOV
49
  const { prefix, words } = bech32.decode(input)
×
50
  if (!input.startsWith(prefix)) {
×
51
    throw new Error(`Bech32 invalid prefix: ${prefix}`)
×
52
  }
53

54
  return Buffer.from(
×
55
    bech32.fromWords(words).slice(0, 32)
56
  ).toString('hex')
57
}
58

59
export const toBech32 = (prefix: string) => (input: string): string => {
1✔
UNCOV
60
  return bech32.encode(prefix, bech32.toWords(Buffer.from(input, 'hex')))
×
61
}
62

63
export const toDate = (input: string | number) => new Date(input)
1✔
64

65
export const fromZebedeeInvoice = applySpec<Invoice>({
1✔
66
  id: prop('id'),
67
  pubkey: prop('internalId'),
68
  bolt11: path(['invoice', 'request']),
69
  amountRequested: pipe(prop('amount') as () => string, toBigInt),
70
  description: prop('description'),
71
  unit: prop('unit'),
72
  status: prop('status'),
73
  expiresAt: ifElse(
74
    propSatisfies(is(String), 'expiresAt'),
75
    pipe(prop('expiresAt'), toDate),
76
    always(null),
77
  ),
78
  confirmedAt: ifElse(
79
    propSatisfies(is(String), 'confirmedAt'),
80
    pipe(prop('confirmedAt'), toDate),
81
    always(null),
82
  ),
83
  createdAt: ifElse(
84
    propSatisfies(is(String), 'createdAt'),
85
    pipe(prop('createdAt'), toDate),
86
    always(null),
87
  ),
88
  rawResponse: toJSON,
89
})
90

91
export const fromNodelessInvoice = applySpec<Invoice>({
1✔
92
  id: prop('id'),
93
  pubkey: path(['metadata', 'requestId']),
94
  bolt11: prop('lightningInvoice'),
95
  amountRequested: pipe(prop('satsAmount') as () => number, toBigInt),
96
  description: path(['metadata', 'description']),
97
  unit: path(['metadata', 'unit']),
98
  status: pipe(
99
    prop('status'),
100
    cond([
101
      [equals('new'), always(InvoiceStatus.PENDING)],
102
      [equals('pending_confirmation'), always(InvoiceStatus.PENDING)],
103
      [equals('underpaid'), always(InvoiceStatus.PENDING)],
104
      [equals('in_flight'), always(InvoiceStatus.PENDING)],
105
      [equals('paid'), always(InvoiceStatus.COMPLETED)],
106
      [equals('overpaid'), always(InvoiceStatus.COMPLETED)],
107
      [equals('expired'), always(InvoiceStatus.EXPIRED)],
108
    ]),
109
  ),
110
  expiresAt: ifElse(
111
    propSatisfies(is(String), 'expiresAt'),
112
    pipe(prop('expiresAt'), toDate),
113
    ifElse(
114
      propSatisfies(is(String), 'createdAt'),
115
      pipe(prop('createdAt'), toDate, addTime(15 * 60000)),
116
      always(null),
117
    ),
118
  ),
119
  confirmedAt: cond([
120
    [propSatisfies(is(String), 'paidAt'), pipe(prop('paidAt'), toDate)],
121
    [T, always(null)],
122
  ]),
123
  createdAt: ifElse(
124
    propSatisfies(is(String), 'createdAt'),
125
    pipe(prop('createdAt'), toDate),
126
    always(null),
127
  ),
128
  // rawResponse: toJSON,
129
})
130

131
export const fromOpenNodeInvoice = applySpec<Invoice>({
1✔
132
  id: prop('id'),
133
  pubkey: prop('order_id'),
134
  bolt11: ifElse(
135
    pathSatisfies(is(String), ['lightning_invoice', 'payreq']),
136
    path(['lightning_invoice', 'payreq']),
137
    path(['lightning', 'payreq'])
138
  ),
139
  amountRequested: pipe(
140
    ifElse(
141
      propSatisfies(is(Number), 'amount'),
142
      prop('amount'),
143
      prop('price'),
144
    ) as () => number,
145
    toBigInt,
146
  ),
147
  description: prop('description'),
148
  unit: always(InvoiceUnit.SATS),
149
  status: pipe(
150
    prop('status'),
151
    cond([
152
      [equals('expired'), always(InvoiceStatus.EXPIRED)],
153
      [equals('refunded'), always(InvoiceStatus.EXPIRED)],
154
      [equals('unpaid'), always(InvoiceStatus.PENDING)],
155
      [equals('processing'), always(InvoiceStatus.PENDING)],
156
      [equals('underpaid'), always(InvoiceStatus.PENDING)],
157
      [equals('paid'), always(InvoiceStatus.COMPLETED)],
158
    ]),
159
  ),
160
  expiresAt: pipe(
161
    cond([
162
      [pathSatisfies(is(String), ['lightning', 'expires_at']), path(['lightning', 'expires_at'])],
163
      [pathSatisfies(is(Number), ['lightning_invoice', 'expires_at']), pipe(path(['lightning_invoice', 'expires_at']), multiply(1000))],
164
    ]),
165
    toDate,
166
  ),
167
  confirmedAt: cond([
UNCOV
168
    [propSatisfies(equals('paid'), 'status'), () => new Date()],
×
169
    [T, always(null)],
170
  ]),
171
  createdAt: pipe(
172
    ifElse(
173
      propSatisfies(is(Number), 'created_at'),
174
      pipe(prop('created_at'), multiply(1000)),
175
      prop('created_at'),
176
    ),
177
    toDate,
178
  ),
179
  rawResponse: toJSON,
180
})
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc