Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 43 additions & 22 deletions react/lib/util/chronik.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,29 @@ export function getNullDataScriptData (outputScript: string): OpReturnData | nul
const opReturnCode = '6a'
const encodedProtocolPushData = '04' // '\x04'
const encodedProtocol = '50415900' // 'PAY\x00'

const prefixLen = (
opReturnCode.length +
encodedProtocolPushData.length +
encodedProtocol.length +
2 // version byte
)

const regexPattern = new RegExp(
`${opReturnCode}${encodedProtocolPushData}${encodedProtocol}.{2}`,
'i'
)

if (!regexPattern.test(outputScript.slice(0, prefixLen))) {
return null
}

let dataStartIndex = prefixLen + 2

if (outputScript.length < dataStartIndex) {
return null
}

let dataPushDataHex = outputScript.slice(prefixLen, dataStartIndex)
if (dataPushDataHex.toLowerCase() === '4c') {
dataStartIndex = dataStartIndex + 2
Expand All @@ -55,26 +55,26 @@ export function getNullDataScriptData (outputScript: string): OpReturnData | nul
if (outputScript.length < dataStartIndex + dataPushData * 2) {
return null
}

const dataHexBuffer = Buffer.from(
outputScript.slice(dataStartIndex, dataStartIndex + dataPushData * 2),
'hex'
)
const dataString = decoder.decode(dataHexBuffer)

const ret: OpReturnData = {
rawMessage: dataString,
message: parseOpReturnData(dataString),
paymentId: ''
}

const paymentIdPushDataIndex = dataStartIndex + dataPushData * 2
const paymentIdStartIndex = paymentIdPushDataIndex + 2
const hasPaymentId = outputScript.length >= paymentIdStartIndex
if (!hasPaymentId) {
return ret
}

const paymentIdPushDataHex = outputScript.slice(paymentIdPushDataIndex, paymentIdStartIndex)
const paymentIdPushData = parseInt(paymentIdPushDataHex, 16)
let paymentIdString = ''
Expand All @@ -87,10 +87,10 @@ export function getNullDataScriptData (outputScript: string): OpReturnData | nul
paymentIdString += hexByte
}
ret.paymentId = paymentIdString

return ret
}

export function toHash160 (address: string): {type: AddressType, hash160: string} {
try {
const { type, hash } = decodeCashAddress(address)
Expand All @@ -103,13 +103,13 @@ export function toHash160 (address: string): {type: AddressType, hash160: string

export async function satoshisToUnit(satoshis: bigint, networkFormat: string): Promise<string> {
const decimal = new Decimal(satoshis.toString())

if (networkFormat === xecaddr.Format.Xecaddr) {
return decimal.div(1e2).toString()
} else if (networkFormat === xecaddr.Format.Cashaddr) {
return decimal.div(1e8).toString()
}

throw new Error('[CHRONIK]: Invalid address')
}

Expand Down Expand Up @@ -148,6 +148,8 @@ const getTransactionAmountAndData = async (transaction: Tx, addressString: stri
const getTransactionFromChronikTransaction = async (transaction: Tx, address: string): Promise<Transaction> => {
const { amount, opReturn } = await getTransactionAmountAndData(transaction, address)
const parsedOpReturn = resolveOpReturn(opReturn)
const networkSlug = getAddressPrefix(address)
const inputAddresses = getSortedInputAddresses(networkSlug, transaction)
return {
hash: transaction.txid,
amount,
Expand All @@ -158,19 +160,20 @@ const getTransactionFromChronikTransaction = async (transaction: Tx, address: st
paymentId: parsedOpReturn?.paymentId ?? '',
message: parsedOpReturn?.message ?? '',
rawMessage: parsedOpReturn?.rawMessage ?? '',
inputAddresses,
}
}

export const fromHash160 = (networkSlug: string, type: AddressType, hash160: string): string => {
const buffer = Buffer.from(hash160, 'hex')

// Because ecashaddrjs only accepts Uint8Array as input type, convert
const hash160ArrayBuffer = new ArrayBuffer(buffer.length)
const hash160Uint8Array = new Uint8Array(hash160ArrayBuffer)
for (let i = 0; i < hash160Uint8Array.length; i += 1) {
hash160Uint8Array[i] = buffer[i]
}

return encodeCashAddress(
networkSlug,
type,
Expand All @@ -180,7 +183,7 @@ export const fromHash160 = (networkSlug: string, type: AddressType, hash160: st

export function outputScriptToAddress (networkSlug: string, outputScript: string | undefined): string | undefined {
if (outputScript === undefined) return undefined

const typeTestSlice = outputScript.slice(0, 4)
let addressType
let hash160
Expand All @@ -202,9 +205,9 @@ export function outputScriptToAddress (networkSlug: string, outputScript: string
default:
return undefined
}

if (hash160.length !== 40) return undefined

return fromHash160(networkSlug, addressType as AddressType, hash160)
}

Expand All @@ -216,12 +219,30 @@ const resolveOpReturn = (opReturn: string): OpReturnData | null => {
}
}

function getSortedInputAddresses (networkSlug: string, transaction: Tx): string[] {
const addressSatsMap = new Map<string, bigint>()

transaction.inputs.forEach((inp) => {
const address = outputScriptToAddress(networkSlug, inp.outputScript)
if (address !== undefined && address !== '') {
const currentValue = addressSatsMap.get(address) ?? BigInt(0)
addressSatsMap.set(address, currentValue + inp.sats)
}
})

const sortedInputAddresses = Array.from(addressSatsMap.entries())
.sort(([, valueA], [, valueB]) => Number(valueB - valueA))
.map(([address]) => address)

return sortedInputAddresses
}

export const parseWebsocketMessage = async (
wsMsg: any,
setNewTx: Function,
chronik: ChronikClient,
address: string
) => {
): Promise<void> => {
const { type } = wsMsg;
if (type === 'Error') {
return;
Expand All @@ -247,7 +268,7 @@ export const initializeChronikWebsocket = async (
): Promise<WsEndpoint> => {
const networkSlug = getAddressPrefix(address)
const blockchainUrls = config.networkBlockchainURLs[networkSlug];

const chronik = await ChronikClient.useStrategy(
ConnectionStrategy.AsOrdered,
blockchainUrls,
Expand All @@ -266,4 +287,4 @@ export const initializeChronikWebsocket = async (
ws.subscribeToAddress(address);

return ws;
};
};
68 changes: 23 additions & 45 deletions react/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,16 @@
resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3"
integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==

"@humanwhocodes/retry@^0.3.0":
version "0.3.1"
resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.1.tgz#c72a5c76a9fbaf3488e231b13dc52c0da7bab42a"
integrity sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==

"@humanwhocodes/retry@^0.4.2":
version "0.4.3"
resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba"
integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==

"@isaacs/balanced-match@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz#3081dadbc3460661b751e7591d7faea5df39dd29"
Expand Down Expand Up @@ -3644,7 +3654,7 @@
"@types/estree" "*"
"@types/json-schema" "*"

"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.8":
"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.6", "@types/estree@^1.0.8":
version "1.0.8"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e"
integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==
Expand Down Expand Up @@ -4418,7 +4428,7 @@ acorn-import-phases@^1.0.3:
resolved "https://registry.yarnpkg.com/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz#16eb850ba99a056cb7cbfe872ffb8972e18c8bd7"
integrity sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==

acorn-jsx@^5.2.0, acorn-jsx@^5.3.1, acorn-jsx@^5.3.2:
acorn-jsx@^5.3.1, acorn-jsx@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
Expand Down Expand Up @@ -5527,7 +5537,7 @@ chronik-client-cashtokens@^3.1.1-rc0:
dependencies:
"@types/ws" "^8.2.1"
axios "^1.6.3"
ecashaddrjs "file:../../../../../Library/Caches/Yarn/v6/npm-chronik-client-cashtokens-3.1.1-rc0-e5e4a3538e8010b70623974a731bf2712506c5e3-integrity/node_modules/ecashaddrjs"
ecashaddrjs "file:../../../.cache/yarn/v6/npm-chronik-client-cashtokens-3.1.1-rc0-e5e4a3538e8010b70623974a731bf2712506c5e3-integrity/node_modules/ecashaddrjs"
isomorphic-ws "^4.0.1"
protobufjs "^6.8.8"
ws "^8.3.0"
Expand Down Expand Up @@ -5974,17 +5984,6 @@ cross-spawn@^4.0.0:
lru-cache "^4.0.1"
which "^1.2.9"

cross-spawn@^6.0.5:
version "6.0.6"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.6.tgz#30d0efa0712ddb7eb5a76e1e8721bffafa6b5d57"
integrity sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
semver "^5.5.0"
shebang-command "^1.2.0"
which "^1.2.9"

cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6:
version "7.0.6"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
Expand Down Expand Up @@ -6381,7 +6380,7 @@ debug@2.6.9, debug@^2.6.0, debug@^2.6.9:
dependencies:
ms "2.0.0"

debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.1:
debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b"
integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
Expand Down Expand Up @@ -6762,7 +6761,7 @@ ecashaddrjs@^1.0.7:
big-integer "1.6.36"
bs58check "^3.0.1"

ecashaddrjs@^2.0.0, "ecashaddrjs@file:../ecashaddrjs":
ecashaddrjs@^2.0.0, "ecashaddrjs@file:../../../../../Library/Caches/Yarn/v6/npm-chronik-client-cashtokens-3.1.1-rc0-e5e4a3538e8010b70623974a731bf2712506c5e3-integrity/node_modules/ecashaddrjs":
version "2.0.0"
resolved "https://registry.yarnpkg.com/ecashaddrjs/-/ecashaddrjs-2.0.0.tgz#d45ede7fb6168815dbcf664b8e0a6872e485d874"
integrity sha512-EvK1V4D3+nIEoD0ggy/b0F4lW39/72R9aOs/scm6kxMVuXu16btc+H74eQv7okNfXaQWKgolEekZkQ6wfcMMLw==
Expand Down Expand Up @@ -7538,7 +7537,7 @@ esprima@^4.0.0, esprima@^4.0.1, esprima@~4.0.0:
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==

esquery@^1.0.1, esquery@^1.4.2:
esquery@^1.4.2, esquery@^1.5.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7"
integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==
Expand Down Expand Up @@ -8302,20 +8301,18 @@ global-prefix@^3.0.0:
kind-of "^6.0.2"
which "^1.3.1"

globals@^12.1.0:
version "12.4.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8"
integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==
dependencies:
type-fest "^0.8.1"

globals@^13.19.0:
version "13.24.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171"
integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==
dependencies:
type-fest "^0.20.2"

globals@^14.0.0:
version "14.0.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e"
integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==

globalthis@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236"
Expand Down Expand Up @@ -8779,7 +8776,7 @@ import-fresh@^2.0.0:
caller-path "^2.0.0"
resolve-from "^3.0.0"

import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1:
import-fresh@^3.1.0, import-fresh@^3.2.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf"
integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==
Expand Down Expand Up @@ -8847,25 +8844,6 @@ ini@^1.3.5:
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==

inquirer@^7.0.0:
version "7.3.3"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003"
integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==
dependencies:
ansi-escapes "^4.2.1"
chalk "^4.1.0"
cli-cursor "^3.1.0"
cli-width "^3.0.0"
external-editor "^3.0.3"
figures "^3.0.0"
lodash "^4.17.19"
mute-stream "0.0.8"
run-async "^2.4.0"
rxjs "^6.6.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"
through "^2.3.6"

internal-slot@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961"
Expand Down Expand Up @@ -13986,7 +13964,7 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.3.0, semver@^6.3.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==

semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.7.2:
semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.7.2:
version "7.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58"
integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==
Expand Down