Skip to content

Commit

Permalink
Merge pull request #312 from pshenmic/feat/signature-and-multiplier
Browse files Browse the repository at this point in the history
Expanding decoding response for transactions
  • Loading branch information
pshenmic authored Nov 26, 2024
2 parents 882ae1f + bf7e3bf commit 4116654
Show file tree
Hide file tree
Showing 13 changed files with 1,351 additions and 111 deletions.
1 change: 1 addition & 0 deletions packages/api/.env
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ DASHCORE_PASS=password
EPOCH_CHANGE_TIME=3600000
DAPI_URL=127.0.0.1:1443:self-signed
TCP_CONNECT_TIMEOUT=400
NETWORK=testnet
525 changes: 488 additions & 37 deletions packages/api/README.md

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"lint": "standard ."
},
"dependencies": {
"@dashevo/dapi-client": "github:owl352/dapi-client",
"@dashevo/dashd-rpc": "19.0.0",
"@dashevo/wasm-dpp": "github:owl352/wasm-dpp",
"@fastify/cors": "^8.3.0",
"@scure/base": "^1.1.5",
"bs58": "^6.0.0",
Expand All @@ -23,8 +25,7 @@
"fastify-metrics": "^11.0.0",
"knex": "^2.5.1",
"node-fetch": "^2.6.11",
"pg": "^8.11.3",
"@dashevo/dapi-client": "github:owl352/dapi-client"
"pg": "^8.11.3"
},
"devDependencies": {
"standard": "^17.1.0",
Expand Down
3 changes: 1 addition & 2 deletions packages/api/src/DAPI.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ class DAPI {
* @param {string} indexName
* @param {number} resultType
* @param {Array<Buffer>} indexValuesList
* @param {Buffer} [startAtIdentifierInfo]
* @param {bool} [allowIncludeLockedAndAbstainingVoteTally]
* @param {StartAtIdentifierInfo} [startAtIdentifierInfo]
* @param {number} [count]
* @returns {Promise<contestedResourceContenders>}
*/
Expand Down
1 change: 1 addition & 0 deletions packages/api/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ module.exports = {
EPOCH_CHANGE_TIME: Number(process.env.EPOCH_CHANGE_TIME),
TCP_CONNECT_TIMEOUT: Number(process.env.TCP_CONNECT_TIMEOUT),
DPNS_CONTRACT: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec',
NETWORK: process.env.NETWORK ?? 'testnet',
get genesisTime () {
if (!genesisTime || isNaN(genesisTime)) {
return TenderdashRPC.getBlockByHeight(1).then((blockInfo) => {
Expand Down
7 changes: 5 additions & 2 deletions packages/api/src/controllers/IdentitiesController.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const IdentitiesDAO = require('../dao/IdentitiesDAO')
const { WITHDRAWAL_CONTRACT_TYPE } = require('../constants')
const WithdrawalsContract = require('../../data_contracts/withdrawals.json')
const PaginatedResultSet = require('../models/PaginatedResultSet')

class IdentitiesController {
constructor (knex, dapi) {
Expand Down Expand Up @@ -90,12 +91,14 @@ class IdentitiesController {
return response.status(404).send({ message: 'not found' })
}

response.send(documents.map(document => ({
const resultSet = documents.map(document => ({
...document,
hash: txHashes.find(
hash =>
new Date(hash.timestamp).toISOString() === new Date(document.timestamp).toISOString())?.hash ?? null
})))
}))

response.send(new PaginatedResultSet(resultSet, null, null, null))
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/dao/TransactionsDAO.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module.exports = class TransactionsDAO {
return null
}

const aliases = await Promise.all(row.aliases.map(async alias => {
const aliases = await Promise.all((row.aliases ?? []).map(async alias => {
const aliasInfo = await getAliasInfo(alias, this.dapi)

const isLocked = base58.encode(
Expand Down
16 changes: 16 additions & 0 deletions packages/api/src/enums/DocumentActionEnum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const DocumentActionEnum = {
0: 'Create',
1: 'Replace',
2: 'Delete',
3: 'Transfer',
4: 'Update price',
5: 'Purchase',
Create: 0,
Replace: 1,
Delete: 2,
Transfer: 3,
UpdatePrice: 4,
Purchase: 5
}

module.exports = DocumentActionEnum
7 changes: 7 additions & 0 deletions packages/api/src/enums/PoolingEnum.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const PoolingEnum = {
0: 'Standard',
1: 'Never',
3: 'If Available'
}

module.exports = PoolingEnum
140 changes: 131 additions & 9 deletions packages/api/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
const crypto = require('crypto')
const StateTransitionEnum = require('./enums/StateTransitionEnum')
const PoolingEnum = require('./enums/PoolingEnum')
const DocumentActionEnum = require('./enums/DocumentActionEnum')
const net = require('net')
const { TCP_CONNECT_TIMEOUT, DPNS_CONTRACT } = require('./constants')
const { TCP_CONNECT_TIMEOUT, DPNS_CONTRACT, NETWORK } = require('./constants')
const { base58 } = require('@scure/base')
const convertToHomographSafeChars = require('dash/build/utils/convertToHomographSafeChars').default
const Intervals = require('./enums/IntervalsEnum')
const dashcorelib = require('@dashevo/dashcore-lib')

const getKnex = () => {
return require('knex')({
Expand Down Expand Up @@ -33,61 +36,175 @@ const decodeStateTransition = async (client, base64) => {

switch (decoded.type) {
case StateTransitionEnum.DATA_CONTRACT_CREATE: {
const dataContractConfig = stateTransition.getDataContract().getConfig()

decoded.internalConfig = {
canBeDeleted: dataContractConfig.canBeDeleted,
readonly: dataContractConfig.readonly,
keepsHistory: dataContractConfig.keepsHistory,
documentsKeepHistoryContractDefault: dataContractConfig.documentsKeepHistoryContractDefault,
documentsMutableContractDefault: dataContractConfig.documentsMutableContractDefault,
documentsCanBeDeletedContractDefault: dataContractConfig.documentsCanBeDeletedContractDefault,
requiresIdentityDecryptionBoundedKey: dataContractConfig.requiresIdentityDecryptionBoundedKey ?? null,
requiresIdentityEncryptionBoundedKey: dataContractConfig.requiresIdentityEncryptionBoundedKey ?? null
}

decoded.userFeeIncrease = stateTransition.toObject().userFeeIncrease
decoded.identityNonce = Number(stateTransition.getIdentityNonce())
decoded.dataContractId = stateTransition.getDataContract().getId().toString()
decoded.identityId = stateTransition.getOwnerId().toString()
decoded.ownerId = stateTransition.getOwnerId().toString()
decoded.schema = stateTransition.getDataContract().getDocumentSchemas()
decoded.signature = Buffer.from(stateTransition.toObject().signature).toString('hex')
decoded.signaturePublicKeyId = stateTransition.toObject().signaturePublicKeyId
decoded.raw = stateTransition.toBuffer().toString('hex')

break
}
case StateTransitionEnum.DOCUMENTS_BATCH: {
decoded.transitions = stateTransition.getTransitions().map((documentTransition) => ({
id: documentTransition.getId().toString(),
dataContractId: documentTransition.getDataContractId().toString(),
action: documentTransition.getAction(),
revision: documentTransition.getRevision()
}))
decoded.transitions = stateTransition.getTransitions().map((documentTransition) => {
const out = {
id: documentTransition.getId().toString(),
dataContractId: documentTransition.getDataContractId().toString(),
revision: documentTransition.getRevision(),
type: documentTransition.getType(),
action: documentTransition.getAction()
}

switch (documentTransition.getAction()) {
case DocumentActionEnum.Create: {
const prefundedBalance = documentTransition.getPrefundedVotingBalance()

out.data = documentTransition.getData()
out.prefundedBalance = prefundedBalance
? Object.fromEntries(
Object.entries(prefundedBalance)
.map(prefund => [prefund[0], Number(prefund[1])])
)
: null

break
}
case DocumentActionEnum.Replace: {
out.data = documentTransition.getData()

break
}
}

return out
})

decoded.userFeeIncrease = stateTransition.getUserFeeIncrease()
decoded.signature = Buffer.from(stateTransition.getSignature()).toString('hex')
decoded.signaturePublicKeyId = stateTransition.getSignaturePublicKeyId()
decoded.ownerId = stateTransition.getOwnerId().toString()
decoded.raw = stateTransition.toBuffer().toString('hex')

break
}
case StateTransitionEnum.IDENTITY_CREATE: {
const assetLockProof = stateTransition.getAssetLockProof()

decoded.fundingAddress = assetLockProof.getOutput
? dashcorelib.Script(assetLockProof.getOutput().script).toAddress(NETWORK).toString()
: null
decoded.assetLockProof = assetLockProof.toJSON()
decoded.userFeeIncrease = stateTransition.getUserFeeIncrease()
decoded.identityId = stateTransition.getIdentityId().toString()
decoded.signature = stateTransition.getSignature()?.toString('hex') ?? null
decoded.raw = stateTransition.toBuffer().toString('hex')
decoded.publicKeys = stateTransition.publicKeys.map(key => ({
...key.toJSON(),
signature: Buffer.from(key.getSignature()).toString('hex')
}))

break
}
case StateTransitionEnum.IDENTITY_TOP_UP: {
const assetLockProof = stateTransition.getAssetLockProof()
const output = assetLockProof.getOutput()

decoded.fundingAddress = assetLockProof.getOutput
? dashcorelib.Script(assetLockProof.getOutput().script).toAddress(NETWORK).toString()
: null
decoded.assetLockProof = assetLockProof.toJSON()
decoded.identityId = stateTransition.getIdentityId().toString()
decoded.amount = output.satoshis * 1000
decoded.signature = stateTransition.getSignature()?.toString('hex') ?? null
decoded.raw = stateTransition.toBuffer().toString('hex')

break
}
case StateTransitionEnum.DATA_CONTRACT_UPDATE: {
decoded.identityId = stateTransition.getDataContract().getOwnerId().toString()
const dataContractConfig = stateTransition.getDataContract().getConfig()

decoded.internalConfig = {
canBeDeleted: dataContractConfig.canBeDeleted,
readonly: dataContractConfig.readonly,
keepsHistory: dataContractConfig.keepsHistory,
documentsKeepHistoryContractDefault: dataContractConfig.documentsKeepHistoryContractDefault,
documentsMutableContractDefault: dataContractConfig.documentsMutableContractDefault,
documentsCanBeDeletedContractDefault: dataContractConfig.documentsCanBeDeletedContractDefault,
requiresIdentityDecryptionBoundedKey: dataContractConfig.requiresIdentityDecryptionBoundedKey ?? null,
requiresIdentityEncryptionBoundedKey: dataContractConfig.requiresIdentityEncryptionBoundedKey ?? null
}

decoded.identityContractNonce = stateTransition.toObject()['$identity-contract-nonce']
decoded.signaturePublicKeyId = stateTransition.toObject().signaturePublicKeyId
decoded.signature = Buffer.from(stateTransition.toObject().signature).toString('hex')
decoded.userFeeIncrease = stateTransition.toObject().userFeeIncrease
decoded.ownerId = stateTransition.getDataContract().getOwnerId().toString()
decoded.dataContractId = stateTransition.getDataContract().getId().toString()
decoded.dataContractNonce = Number(stateTransition.getDataContract().getIdentityNonce())
decoded.schema = stateTransition.getDataContract().getDocumentSchemas()
decoded.version = stateTransition.getDataContract().getVersion()
decoded.dataContractOwner = stateTransition.getDataContract().getOwnerId().toString()
decoded.raw = stateTransition.toBuffer().toString('hex')

break
}
case StateTransitionEnum.IDENTITY_UPDATE: {
decoded.identityContractNonce = Number(stateTransition.getIdentityContractNonce())
decoded.userFeeIncrease = stateTransition.getUserFeeIncrease()
decoded.identityId = stateTransition.getOwnerId().toString()
decoded.revision = stateTransition.getRevision()
decoded.publicKeysToAdd = stateTransition.getPublicKeysToAdd()
.map(key => ({
...key.toJSON(),
signature: Buffer.from(key.getSignature()).toString('hex')
}))
decoded.setPublicKeyIdsToDisable = (stateTransition.getPublicKeyIdsToDisable() ?? []).map(key => key.toJSON())
decoded.signature = stateTransition.getSignature().toString('hex')
decoded.signaturePublicKeyId = stateTransition.toObject().signaturePublicKeyId
decoded.raw = stateTransition.toBuffer().toString('hex')

break
}
case StateTransitionEnum.IDENTITY_CREDIT_TRANSFER: {
decoded.identityContractNonce = Number(stateTransition.getIdentityContractNonce())
decoded.userFeeIncrease = stateTransition.getUserFeeIncrease()
decoded.senderId = stateTransition.getIdentityId().toString()
decoded.recipientId = stateTransition.getRecipientId().toString()
decoded.amount = stateTransition.getAmount()
decoded.signaturePublicKeyId = stateTransition.toObject().signaturePublicKeyId
decoded.signature = stateTransition.getSignature()?.toString('hex') ?? null
decoded.raw = stateTransition.toBuffer().toString('hex')

break
}
case StateTransitionEnum.IDENTITY_CREDIT_WITHDRAWAL: {
decoded.outputAddress = dashcorelib.Script(stateTransition.getOutputScript()).toAddress(NETWORK).toString()
decoded.userFeeIncrease = stateTransition.getUserFeeIncrease()
decoded.identityContractNonce = Number(stateTransition.getIdentityContractNonce())
decoded.senderId = stateTransition.getIdentityId().toString()
decoded.amount = parseInt(stateTransition.getAmount())
decoded.nonce = parseInt(stateTransition.getNonce())
decoded.outputScript = stateTransition.getOutputScript()?.toString('hex') ?? null
decoded.coreFeePerByte = stateTransition.getCoreFeePerByte()
decoded.signature = stateTransition.getSignature()?.toString('hex')
decoded.signaturePublicKeyId = stateTransition.toObject().signaturePublicKeyId
decoded.pooling = PoolingEnum[stateTransition.getPooling()]
decoded.raw = stateTransition.toBuffer().toString('hex')

break
}
Expand All @@ -96,6 +213,11 @@ const decodeStateTransition = async (client, base64) => {
decoded.contractId = stateTransition.getContestedDocumentResourceVotePoll().contractId.toString()
decoded.modifiedDataIds = stateTransition.getModifiedDataIds().map(identifier => identifier.toString())
decoded.ownerId = stateTransition.getOwnerId().toString()
decoded.signature = stateTransition.getSignature()?.toString('hex') ?? null
decoded.documentTypeName = stateTransition.getContestedDocumentResourceVotePoll().documentTypeName
decoded.indexName = stateTransition.getContestedDocumentResourceVotePoll().indexName
decoded.choice = stateTransition.getContestedDocumentResourceVotePoll().choice
decoded.raw = stateTransition.toBuffer().toString('hex')

break
}
Expand Down
2 changes: 1 addition & 1 deletion packages/api/test/integration/identities.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ describe('Identities routes', () => {
.expect(200)
.expect('Content-Type', 'application/json; charset=utf-8')

assert.deepEqual(body, withdrawals.map(withdrawal => ({ ...withdrawal, hash: withdrawal.id })))
assert.deepEqual(body.resultSet, withdrawals.map(withdrawal => ({ ...withdrawal, hash: withdrawal.id })))
})

it('should return 404 whe identity not exist', async () => {
Expand Down
Loading

0 comments on commit 4116654

Please sign in to comment.