Skip to content

Commit a74a5d2

Browse files
committed
Merge branch 'master' into feat/async-and-improved-initialization
2 parents 4e4db8c + cc89e06 commit a74a5d2

File tree

13 files changed

+467
-234
lines changed

13 files changed

+467
-234
lines changed

.githooks/pre-commit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#!/bin/sh
2-
npx lint-staged
2+
yarn lint-staged

components/Paybutton/PaybuttonTrigger.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ export default ({ paybuttonId, emailCredits }: IProps): JSX.Element => {
213213
<div>&lt;opReturn&gt;</div>
214214
<div>&lt;signature&gt;</div>
215215
<div>&lt;inputAddresses&gt;</div>
216+
<div>&lt;outputAddresses&gt;</div>
216217
<div>&lt;value&gt;</div>
217218

218219
</div>

constants/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ export const TRIGGER_POST_VARIABLES = [
238238
'<timestamp>',
239239
'<txId>',
240240
'<inputAddresses>',
241+
'<outputAddresses>',
241242
'<value>'
242243
]
243244

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"ci:integration:test": "yarn pretest && dotenv -e .env.test -- ts-node -O '{\"module\":\"commonjs\"}' node_modules/jest/bin/jest.js tests/integration-tests --forceExit",
2020
"tarDebug": "tar cf debug.tar logs/ paybutton-config.json .env*",
2121
"updateAllPrices": "./scripts/update-all-prices.sh",
22-
"updateAllPriceConnections": "./scripts/update-all-price-connections.sh"
22+
"updateAllPriceConnections": "./scripts/update-all-price-connections.sh",
23+
"lint-staged": "lint-staged"
2324
},
2425
"dependencies": {
2526
"@emotion/react": "^11.8.2",
@@ -99,8 +100,8 @@
99100
"chronik-client-cashtokens/ecashaddrjs": "^2.0.0"
100101
},
101102
"lint-staged": {
102-
"*.ts?(x)": [
103-
"yarn eslint --fix"
103+
"*.{ts,tsx}": [
104+
"node ./node_modules/eslint/bin/eslint.js --fix"
104105
]
105106
}
106107
}

services/chronikService.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -503,22 +503,47 @@ export class ChronikBlockchainClient {
503503
}
504504
}
505505

506-
private getSortedInputAddresses (transaction: Tx): string[] {
506+
private getSortedInputAddresses (transaction: Tx): Array<{address: string, amount: Prisma.Decimal}> {
507507
const addressSatsMap = new Map<string, bigint>()
508-
509508
transaction.inputs.forEach((inp) => {
510509
const address = outputScriptToAddress(this.networkSlug, inp.outputScript)
511510
if (address !== undefined && address !== '') {
512511
const currentValue = addressSatsMap.get(address) ?? 0n
513512
addressSatsMap.set(address, currentValue + inp.sats)
514513
}
515514
})
516-
515+
const unitDivisor = this.networkId === XEC_NETWORK_ID
516+
? 1e2
517+
: (this.networkId === BCH_NETWORK_ID ? 1e8 : 1)
517518
const sortedInputAddresses = Array.from(addressSatsMap.entries())
518519
.sort(([, valueA], [, valueB]) => Number(valueB - valueA))
519-
.map(([address]) => address)
520+
return sortedInputAddresses.map(([address, sats]) => {
521+
const decimal = new Prisma.Decimal(sats.toString())
522+
const amount = decimal.dividedBy(unitDivisor)
523+
return { address, amount }
524+
})
525+
}
520526

521-
return sortedInputAddresses
527+
private getSortedOutputAddresses (transaction: Tx): Array<{address: string, amount: Prisma.Decimal}> {
528+
const addressSatsMap = new Map<string, bigint>()
529+
transaction.outputs.forEach((out) => {
530+
const address = outputScriptToAddress(this.networkSlug, out.outputScript)
531+
if (address !== undefined && address !== '') {
532+
const currentValue = addressSatsMap.get(address) ?? 0n
533+
addressSatsMap.set(address, currentValue + out.sats)
534+
}
535+
})
536+
const unitDivisor = this.networkId === XEC_NETWORK_ID
537+
? 1e2
538+
: (this.networkId === BCH_NETWORK_ID ? 1e8 : 1)
539+
const sortedOutputAddresses = Array.from(addressSatsMap.entries())
540+
.sort(([, valueA], [, valueB]) => Number(valueB - valueA))
541+
.map(([address, sats]) => {
542+
const decimal = new Prisma.Decimal(sats.toString())
543+
const amount = decimal.dividedBy(unitDivisor)
544+
return { address, amount }
545+
})
546+
return sortedOutputAddresses
522547
}
523548

524549
public async waitForSyncing (txId: string, addressStringArray: string[]): Promise<void> {
@@ -565,10 +590,11 @@ export class ChronikBlockchainClient {
565590
const addressesWithTransactions = await this.getAddressesForTransaction(transaction)
566591
await this.waitForSyncing(msg.txid, addressesWithTransactions.map(obj => obj.address.address))
567592
const inputAddresses = this.getSortedInputAddresses(transaction)
593+
const outputAddresses = this.getSortedOutputAddresses(transaction)
568594
for (const addressWithTransaction of addressesWithTransactions) {
569595
const { created, tx } = await upsertTransaction(addressWithTransaction.transaction)
570596
if (tx !== undefined) {
571-
const broadcastTxData = this.broadcastIncomingTx(addressWithTransaction.address.address, tx, inputAddresses)
597+
const broadcastTxData = this.broadcastIncomingTx(addressWithTransaction.address.address, tx, inputAddresses, outputAddresses)
572598
if (created) { // only execute trigger for newly added txs
573599
await executeAddressTriggers(broadcastTxData, tx.address.networkId)
574600
}
@@ -592,11 +618,11 @@ export class ChronikBlockchainClient {
592618
}
593619
}
594620

595-
private broadcastIncomingTx (addressString: string, createdTx: TransactionWithAddressAndPrices, inputAddresses: string[]): BroadcastTxData {
621+
private broadcastIncomingTx (addressString: string, createdTx: TransactionWithAddressAndPrices, inputAddresses: Array<{address: string, amount: Prisma.Decimal}>, outputAddresses: Array<{address: string, amount: Prisma.Decimal}>): BroadcastTxData {
596622
const broadcastTxData: BroadcastTxData = {} as BroadcastTxData
597623
broadcastTxData.address = addressString
598624
broadcastTxData.messageType = 'NewTx'
599-
const newSimplifiedTransaction = getSimplifiedTrasaction(createdTx, inputAddresses)
625+
const newSimplifiedTransaction = getSimplifiedTrasaction(createdTx, inputAddresses, outputAddresses)
600626
broadcastTxData.txs = [newSimplifiedTransaction]
601627
try { // emit broadcast for both unconfirmed and confirmed txs
602628
this.wsEndpoint.emit(SOCKET_MESSAGES.TXS_BROADCAST, broadcastTxData)
@@ -620,11 +646,12 @@ export class ChronikBlockchainClient {
620646
for (const transaction of blockTxsToSync) {
621647
const addressesWithTransactions = await this.getAddressesForTransaction(transaction)
622648
const inputAddresses = this.getSortedInputAddresses(transaction)
649+
const outputAddresses = this.getSortedOutputAddresses(transaction)
623650

624651
for (const addressWithTransaction of addressesWithTransactions) {
625652
const { created, tx } = await upsertTransaction(addressWithTransaction.transaction)
626653
if (tx !== undefined) {
627-
const broadcastTxData = this.broadcastIncomingTx(addressWithTransaction.address.address, tx, inputAddresses)
654+
const broadcastTxData = this.broadcastIncomingTx(addressWithTransaction.address.address, tx, inputAddresses, outputAddresses)
628655
if (created) { // only execute trigger for newly added txs
629656
await executeAddressTriggers(broadcastTxData, tx.address.networkId)
630657
}

services/transactionService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function getSimplifiedTransactions (transactionsToPersist: TransactionWit
4141
return simplifiedTransactions
4242
}
4343

44-
export function getSimplifiedTrasaction (tx: TransactionWithAddressAndPrices, inputAddresses?: string[]): SimplifiedTransaction {
44+
export function getSimplifiedTrasaction (tx: TransactionWithAddressAndPrices, inputAddresses?: Array<{address: string, amount: Prisma.Decimal}>, outputAddresses?: Array<{address: string, amount: Prisma.Decimal}>): SimplifiedTransaction {
4545
const {
4646
hash,
4747
amount,
@@ -63,6 +63,7 @@ export function getSimplifiedTrasaction (tx: TransactionWithAddressAndPrices, in
6363
message: parsedOpReturn?.message ?? '',
6464
rawMessage: parsedOpReturn?.rawMessage ?? '',
6565
inputAddresses: inputAddresses ?? [],
66+
outputAddresses: outputAddresses ?? [],
6667
prices: tx.prices
6768
}
6869

services/triggerService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ export interface PostDataParameters {
250250
buttonName: string
251251
address: string
252252
opReturn: OpReturnData
253-
inputAddresses?: string[]
253+
inputAddresses?: Array<{address: string, amount: Prisma.Decimal}>
254+
outputAddresses?: Array<{address: string, amount: Prisma.Decimal}>
254255
value: string
255256
}
256257

tests/unittests/transactionService.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,28 @@ describe('Fetch transactions by paybuttonId', () => {
169169
}
170170
})
171171
})
172+
173+
describe('Address object arrays (input/output) integration', () => {
174+
it('getSimplifiedTrasaction returns provided input/output address objects untouched', () => {
175+
const tx: any = {
176+
hash: 'hash1',
177+
amount: new Prisma.Decimal(5),
178+
confirmed: true,
179+
opReturn: '',
180+
address: { address: 'ecash:qqprimaryaddressxxxxxxxxxxxxxxxxxxxxx' },
181+
timestamp: 1700000000,
182+
prices: mockedTransaction.prices
183+
}
184+
const inputs = [
185+
{ address: 'ecash:qqinput1', amount: new Prisma.Decimal(1.23) },
186+
{ address: 'ecash:qqinput2', amount: new Prisma.Decimal(4.56) }
187+
]
188+
const outputs = [
189+
{ address: 'ecash:qqout1', amount: new Prisma.Decimal(7.89) },
190+
{ address: 'ecash:qqout2', amount: new Prisma.Decimal(0.12) }
191+
]
192+
const simplified = transactionService.getSimplifiedTrasaction(tx, inputs, outputs)
193+
expect(simplified.inputAddresses).toEqual(inputs)
194+
expect(simplified.outputAddresses).toEqual(outputs)
195+
})
196+
})

0 commit comments

Comments
 (0)