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

cameri / nostream / 24610041211

18 Apr 2026 05:30PM UTC coverage: 63.346% (+0.5%) from 62.807%
24610041211

Pull #498

github

web-flow
Merge 90e995e5b into 26bcdd51d
Pull Request #498: Implement caching for user admission check

827 of 1385 branches covered (59.71%)

Branch coverage included in aggregate %.

374 of 647 new or added lines in 82 files covered. (57.81%)

19 existing lines in 10 files now uncovered.

2123 of 3272 relevant lines covered (64.88%)

10.46 hits per line

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

81.48
/src/utils/transform.ts
1
import {
2✔
2
  always,
3
  applySpec,
4
  cond,
5
  equals,
6
  ifElse,
7
  is,
8
  isNil,
9
  multiply,
10
  path,
11
  pathSatisfies,
12
  pipe,
13
  prop,
14
  propSatisfies,
15
  T,
16
} from 'ramda'
17
import { bech32 } from 'bech32'
2✔
18

19
import { Invoice, InvoiceStatus, InvoiceUnit } from '../@types/invoice'
2✔
20
import { User } from '../@types/user'
21

22
export const toJSON = (input: any) => JSON.stringify(input)
36✔
23

24
export const toBuffer = (input: any) => Buffer.from(input, 'hex')
334✔
25

26
export const fromBuffer = (input: Buffer) => input.toString('hex')
115✔
27

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

30
export const fromBigInt = (input: bigint) => input.toString()
2✔
31

32
const addTime = (ms: number) => (input: Date) => new Date(input.getTime() + ms)
5✔
33

34
export const fromDBInvoice = applySpec<Invoice>({
2✔
35
  id: prop('id') as () => string,
36
  pubkey: pipe(prop('pubkey') as () => Buffer, fromBuffer),
37
  bolt11: prop('bolt11'),
38
  amountRequested: pipe(prop('amount_requested') as () => string, toBigInt),
39
  amountPaid: ifElse(
40
    propSatisfies(isNil, 'amount_paid'),
41
    always(undefined),
42
    pipe(prop('amount_paid') as () => string, toBigInt),
43
  ),
44
  unit: prop('unit'),
45
  status: prop('status'),
46
  description: prop('description'),
47
  confirmedAt: prop('confirmed_at'),
48
  expiresAt: prop('expires_at'),
49
  updatedAt: prop('updated_at'),
50
  createdAt: prop('created_at'),
51
  verifyURL: prop('verify_url'),
52
})
53

54
export const fromDBUser = applySpec<User>({
2✔
55
  pubkey: pipe(prop('pubkey') as () => Buffer, fromBuffer),
56
  isAdmitted: prop('is_admitted'),
57
  isVanished: prop('is_vanished'),
58
  balance: prop('balance'),
59
  createdAt: prop('created_at'),
60
  updatedAt: prop('updated_at'),
61
})
62

63
export const fromBech32 = (input: string) => {
2✔
64
  const { prefix, words } = bech32.decode(input)
1✔
65
  if (!input.startsWith(prefix)) {
×
66
    throw new Error(`Bech32 invalid prefix: ${prefix}`)
×
67
  }
68

NEW
69
  return Buffer.from(bech32.fromWords(words).slice(0, 32)).toString('hex')
×
70
}
71

72
export const toBech32 =
2✔
73
  (prefix: string) =>
2✔
74
  (input: string): string => {
8✔
75
    return bech32.encode(prefix, bech32.toWords(Buffer.from(input, 'hex')))
8✔
76
  }
77

78
export const toDate = (input: string | number) => new Date(input)
25✔
79

80
export const fromZebedeeInvoice = applySpec<Invoice>({
2✔
81
  id: prop('id'),
82
  pubkey: prop('internalId'),
83
  bolt11: path(['invoice', 'request']),
84
  amountRequested: pipe(prop('amount') as () => string, toBigInt),
85
  description: prop('description'),
86
  unit: prop('unit'),
87
  status: prop('status'),
88
  expiresAt: ifElse(propSatisfies(is(String), 'expiresAt'), pipe(prop('expiresAt'), toDate), always(null)),
89
  confirmedAt: ifElse(propSatisfies(is(String), 'confirmedAt'), pipe(prop('confirmedAt'), toDate), always(null)),
90
  createdAt: ifElse(propSatisfies(is(String), 'createdAt'), pipe(prop('createdAt'), toDate), always(null)),
91
  rawResponse: toJSON,
92
})
93

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

126
export const fromOpenNodeInvoice = applySpec<Invoice>({
2✔
127
  id: prop('id'),
128
  pubkey: prop('order_id'),
129
  bolt11: ifElse(
130
    pathSatisfies(is(String), ['lightning_invoice', 'payreq']),
131
    path(['lightning_invoice', 'payreq']),
132
    path(['lightning', 'payreq']),
133
  ),
134
  amountRequested: pipe(
135
    ifElse(propSatisfies(is(Number), 'amount'), prop('amount'), prop('price')) as () => number,
136
    toBigInt,
137
  ),
138
  description: prop('description'),
139
  unit: always(InvoiceUnit.SATS),
140
  status: pipe(
141
    prop('status'),
142
    cond([
143
      [equals('expired'), always(InvoiceStatus.EXPIRED)],
144
      [equals('refunded'), always(InvoiceStatus.EXPIRED)],
145
      [equals('unpaid'), always(InvoiceStatus.PENDING)],
146
      [equals('processing'), always(InvoiceStatus.PENDING)],
147
      [equals('underpaid'), always(InvoiceStatus.PENDING)],
148
      [equals('paid'), always(InvoiceStatus.COMPLETED)],
149
    ]),
150
  ),
151
  expiresAt: pipe(
152
    cond([
153
      [pathSatisfies(is(String), ['lightning', 'expires_at']), path(['lightning', 'expires_at'])],
154
      [
155
        pathSatisfies(is(Number), ['lightning_invoice', 'expires_at']),
156
        pipe(path(['lightning_invoice', 'expires_at']), multiply(1000)),
157
      ],
158
    ]),
159
    toDate,
160
  ),
161
  confirmedAt: cond([
162
    [propSatisfies(equals('paid'), 'status'), () => new Date()],
3✔
163
    [T, always(null)],
164
  ]),
165
  createdAt: pipe(
166
    ifElse(propSatisfies(is(Number), 'created_at'), pipe(prop('created_at'), multiply(1000)), prop('created_at')),
167
    toDate,
168
  ),
169
  rawResponse: toJSON,
170
})
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