Skip to content

Commit

Permalink
Merge pull request #79 from pshenmic/fix/decode
Browse files Browse the repository at this point in the history
Fix decoding state transition API
  • Loading branch information
pshenmic authored Nov 1, 2023
2 parents e7c5bb5 + eeeac76 commit 4218e7e
Show file tree
Hide file tree
Showing 11 changed files with 206 additions and 14 deletions.
5 changes: 3 additions & 2 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "node index.js"
"start": "node index.js",
"test": "node --test"
},
"dependencies": {
"@fastify/cors": "^8.3.0",
"dash": "^3.25.0-dev.21",
"dash": "^3.25.8",
"dotenv": "^16.3.1",
"fastify": "^4.21.0",
"knex": "^2.5.1",
Expand Down
14 changes: 3 additions & 11 deletions packages/api/src/controllers/TransactionsController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const cache = require("../cache");
const TransactionsDAO = require("../dao/TransactionsDAO");
const utils = require("../utils");

class TransactionsController {
constructor(client, knex) {
Expand Down Expand Up @@ -34,17 +34,9 @@ class TransactionsController {
decode = async (request, reply) => {
const {base64} = request.body;

const cached = cache.get('decoded_' + base64)
const decoded = await utils.decodeStateTransition(this.client, base64)

if (cached) {
return reply.send(cached)
}

const stateTransition = await this.client.platform.dpp.stateTransition.createFromBuffer(Buffer.from(base64, 'base64'));

cache.set('decoded_' + base64, stateTransition)

reply.send(stateTransition)
reply.send(decoded)
}
}

Expand Down
79 changes: 78 additions & 1 deletion packages/api/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,84 @@
const crypto = require('crypto')

const StateTransitionEnum = {
DATA_CONTRACT_CREATE: 0,
DOCUMENTS_BATCH: 1,
IDENTITY_CREATE: 2,
IDENTITY_TOP_UP: 3,
DATA_CONTRACT_UPDATE: 4,
IDENTITY_UPDATE: 5,
IDENTITY_CREDIT_WITHDRAWAL:6,
IDENTITY_CREDIT_TRANSFER: 7
};

const hash = (data) => {
return crypto.createHash('sha1').update(data).digest('hex');
}

module.exports = {hash}
const decodeStateTransition = async (client, base64) => {
const stateTransition = await client.platform.dpp.stateTransition.createFromBuffer(Buffer.from(base64, 'base64'));

const decoded = {
type: stateTransition.getType()
}

switch (decoded.type) {
case StateTransitionEnum.DATA_CONTRACT_CREATE: {
decoded.dataContractId = stateTransition.getDataContract().getId().toString()

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(),
createdAt: documentTransition.getCreatedAt(),
updatedAt: documentTransition.getUpdatedAt()
}))

break
}
case StateTransitionEnum.IDENTITY_CREATE: {
decoded.identityId = stateTransition.getIdentityId().toString()

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

decoded.identityId = stateTransition.getIdentityId().toString()
decoded.amount = output.satoshis * 1000;

break
}
case StateTransitionEnum.DATA_CONTRACT_UPDATE: {
decoded.identityId = stateTransition.getDataContract().getOwnerId().toString()
decoded.dataContractId = stateTransition.getDataContract().getId().toString()
decoded.version = stateTransition.getDataContract().getVersion()

break
}
case StateTransitionEnum.IDENTITY_UPDATE: {
decoded.identityId = stateTransition.getOwnerId().toString()
decoded.revision = stateTransition.getRevision()

break
}
case StateTransitionEnum.IDENTITY_CREDIT_TRANSFER: {
decoded.senderId = stateTransition.getIdentityId().toString()
decoded.recipientId = stateTransition.getRecipientId().toString()
decoded.amount = stateTransition.getAmount()

break
}
default:
throw new Error('Unknown state transition')
}

return decoded;
}

module.exports = {hash, decodeStateTransition}
3 changes: 3 additions & 0 deletions packages/api/test/mocks/create_identity.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"data": "AwADAAAAAAAAACECBo6/3B1v9MjNQk7qz+iIjbqMI5xcK7VeSzjvr5MH6cJBIFGKWcJX4Bhdp3QAS7pYQ0J0STGeCfk8sT6nDbP51BF2QRfol10F/FcLqmyyE3IXM6y99J33BaZMiO0XtuBAqTQAAQAAAgAAIQMiB4r6bmJ3Q7ry+4Jra4oBdlooVu7dIZ1kRd+lbHo8LEEfo8qGTynMiGnGwf3Bjj3wTb9o5ijjHnXLnIIOqmuHhIIS8taVCz2V7kC5HcsqoQRtS3mINV0wlPyTY5/LOUVAfQACAAABAAAhAj616IiNVKTGahG4Y2rlCJJfG+NX8c5JpnbgReqNsTmCQSCo/RKmvdcGVKhe0kJgM0wEBXTcFQ+fLvNgpZKXIuKE7XNe2KrjzaaKQspAo4Cj8D/HRDb6v9ISzpjsMG7b2fQcAADGAQHLot/qaNvFu1jrTdSRFySR4RSaLiTBpP0entJLoyWBxQEAAADrv2CkEe9kouFn64JTIOHfVPCuZMbE8DC08nqMarSNooL24fPlSczbBaSv3W1H3t3KYfuxpDDCoElNJnexAAAAkrR4VIZPM0XHVaNs1+j4NJR+bNH9Bxw93YvlL8REdicRuH0e4651vPXnpDt7bloSFNTUNBgXIRiByBz6joWaBnKyF5srhBMNuPGbG7zw0wtdV78ED17MQ3zHoa0X2lfH3gMAAAABy6Lf6mjbxbtY603UkRckkeEUmi4kwaT9Hp7SS6MlgcUBAAAAakcwRAIgYtSf9I1uxuv1DjA/crUImVrzHJSfIvcqKyirNrs35nYCIFFAr/wsUws/5BDUsEwp1guPOBT8OfKF5uEsISF1HwMMASECA20hNKI/dvVCapQO6B4cOw1MgqsvlczI8MSyG/KXonD/////AkBCDwAAAAAAFmoUvQfKZ9f0Fqe+LRU7K3YtnYoTwAyg0o1LAgAAABl2qRQV6d1VA9SLk5WIMESnlKyLpV/5FIisAAAAAABBIK+48nYrgqSa6zNKSe5qrDfXhsoYirac6se02bvjyA/rL5Q0C4+8ibIsRlLaBL+sPWhmMpDycZ5/Lm0w/YMvIh1dOu5sX0X10BpbWM8TT6LxFqMlksSzsk1eslzzJFupsQ=="
}
3 changes: 3 additions & 0 deletions packages/api/test/mocks/data_contract_create.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"data": "AAAAOs1K0En9szQITlmEHzVOvFwfrUo913sSlnsMx0aISfUAAAAAAAEAAAFXdaWxZR5HSzQDPnrqVb7rLwAsFIV3arfY3rfBVEPfQAADCmRnbWFkZHJlc3MWBRIEdHlwZRIGb2JqZWN0EgdpbmRpY2VzFQEWAxIEbmFtZRIHb3duZXJJZBIKcHJvcGVydGllcxUBFgESCCRvd25lcklkEgNhc2MSBnVuaXF1ZRMAEgpwcm9wZXJ0aWVzFgESB2FkZHJlc3MWAxIEdHlwZRIGc3RyaW5nEgltaW5MZW5ndGgDRBIJbWF4TGVuZ3RoA0QSCHJlcXVpcmVkFQESB2FkZHJlc3MSFGFkZGl0aW9uYWxQcm9wZXJ0aWVzEwAGZGdtbXNnFgUSBHR5cGUSBm9iamVjdBIHaW5kaWNlcxUCFgMSBG5hbWUSE293bmVySWRBbmRjcmVhdGVkQXQSCnByb3BlcnRpZXMVAhYBEggkb3duZXJJZBIDYXNjFgESCiRjcmVhdGVkQXQSA2FzYxIGdW5pcXVlEwAWAxIEbmFtZRIQdG9JZGFuZGNyZWF0ZWRBdBIKcHJvcGVydGllcxUCFgESBHRvSWQSA2FzYxYBEgokY3JlYXRlZEF0EgNhc2MSBnVuaXF1ZRMAEgpwcm9wZXJ0aWVzFgMSA21zZxYDEgR0eXBlEgZzdHJpbmcSCW1pbkxlbmd0aAMCEgltYXhMZW5ndGgD+wH0EgR0b0lkFgUSBHR5cGUSBWFycmF5EglieXRlQXJyYXkTARIIbWluSXRlbXMDQBIIbWF4SXRlbXMDQBIQY29udGVudE1lZGlhVHlwZRIhYXBwbGljYXRpb24veC5kYXNoLmRwcC5pZGVudGlmaWVyEgR0eElkFgMSBHR5cGUSBnN0cmluZxIJbWluTGVuZ3RoA4ASCW1heExlbmd0aAOAEghyZXF1aXJlZBUEEgR0b0lkEgR0eElkEgokY3JlYXRlZEF0EgokdXBkYXRlZEF0EhRhZGRpdGlvbmFsUHJvcGVydGllcxMABmRnbXRochYFEgR0eXBlEgZvYmplY3QSB2luZGljZXMVARYDEgRuYW1lEhFtc2dJZGFuZGNyZWF0ZWRBdBIKcHJvcGVydGllcxUCFgESBW1zZ0lkEgNhc2MWARIKJGNyZWF0ZWRBdBIDYXNjEgZ1bmlxdWUTABIKcHJvcGVydGllcxYCEgNtc2cWAxIEdHlwZRIGc3RyaW5nEgltaW5MZW5ndGgDAhIJbWF4TGVuZ3RoA/sB9BIFbXNnSWQWBRIEdHlwZRIFYXJyYXkSCWJ5dGVBcnJheRMBEghtaW5JdGVtcwNAEghtYXhJdGVtcwNAEhBjb250ZW50TWVkaWFUeXBlEiFhcHBsaWNhdGlvbi94LmRhc2guZHBwLmlkZW50aWZpZXISCHJlcXVpcmVkFQQSA21zZxIFbXNnSWQSCiRjcmVhdGVkQXQSCiR1cGRhdGVkQXQSFGFkZGl0aW9uYWxQcm9wZXJ0aWVzEwDgBn3PWAhr5jDs2OGdsMW8EgXbMnTsJ3niXUJD0eu/QwJBH9Zev0cbJTA75cloYEN+cZwdVNmv9JXbTIa0neTq6kYtJD2dlCEPYULwRHmPadgSNtVkbcIwTOZwJanCrFVm+oU="
}
3 changes: 3 additions & 0 deletions packages/api/test/mocks/data_contract_update.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"data": "AQAAVTUZcqmrbvgS8sJwxdL2w3zU+H/VxaEdFSejuabazv8AAAABAAEAAALAk4c76lKdKcgk7dgkMyWYq1OlZvYPVnTh9lR3ATVTlAAED2luZGV4ZWREb2N1bWVudBYFEgR0eXBlEgZvYmplY3QSB2luZGljZXMVBhYDEgRuYW1lEgZpbmRleDESCnByb3BlcnRpZXMVAhYBEggkb3duZXJJZBIDYXNjFgESCWZpcnN0TmFtZRIDYXNjEgZ1bmlxdWUTARYDEgRuYW1lEgZpbmRleDISCnByb3BlcnRpZXMVAhYBEggkb3duZXJJZBIDYXNjFgESCGxhc3ROYW1lEgNhc2MSBnVuaXF1ZRMBFgISBG5hbWUSBmluZGV4MxIKcHJvcGVydGllcxUBFgESCGxhc3ROYW1lEgNhc2MWAhIEbmFtZRIGaW5kZXg0Egpwcm9wZXJ0aWVzFQIWARIKJGNyZWF0ZWRBdBIDYXNjFgESCiR1cGRhdGVkQXQSA2FzYxYCEgRuYW1lEgZpbmRleDUSCnByb3BlcnRpZXMVARYBEgokdXBkYXRlZEF0EgNhc2MWAhIEbmFtZRIGaW5kZXg2Egpwcm9wZXJ0aWVzFQEWARIKJGNyZWF0ZWRBdBIDYXNjEgpwcm9wZXJ0aWVzFgISCWZpcnN0TmFtZRYCEgR0eXBlEgZzdHJpbmcSCW1heExlbmd0aAN+EghsYXN0TmFtZRYCEgR0eXBlEgZzdHJpbmcSCW1heExlbmd0aAN+EghyZXF1aXJlZBUEEglmaXJzdE5hbWUSCiRjcmVhdGVkQXQSCiR1cGRhdGVkQXQSCGxhc3ROYW1lEhRhZGRpdGlvbmFsUHJvcGVydGllcxMAEW15QXdlc29tZURvY3VtZW50FgUSBHR5cGUSBm9iamVjdBIHaW5kaWNlcxUCFgMSBG5hbWUSCWZpcnN0TmFtZRIKcHJvcGVydGllcxUBFgESCWZpcnN0TmFtZRIDYXNjEgZ1bmlxdWUTARYDEgRuYW1lEhFmaXJzdE5hbWVMYXN0TmFtZRIKcHJvcGVydGllcxUCFgESCWZpcnN0TmFtZRIDYXNjFgESCGxhc3ROYW1lEgNhc2MSBnVuaXF1ZRMBEgpwcm9wZXJ0aWVzFgISCWZpcnN0TmFtZRYCEgR0eXBlEgZzdHJpbmcSCW1heExlbmd0aAI/EghsYXN0TmFtZRYCEgR0eXBlEgZzdHJpbmcSCW1heExlbmd0aAI/EghyZXF1aXJlZBUEEglmaXJzdE5hbWUSCiRjcmVhdGVkQXQSCiR1cGRhdGVkQXQSCGxhc3ROYW1lEhRhZGRpdGlvbmFsUHJvcGVydGllcxMADG5pY2VEb2N1bWVudBYEEgR0eXBlEgZvYmplY3QSCnByb3BlcnRpZXMWARIEbmFtZRYBEgR0eXBlEgZzdHJpbmcSCHJlcXVpcmVkFQESCiRjcmVhdGVkQXQSFGFkZGl0aW9uYWxQcm9wZXJ0aWVzEwAOd2l0aEJ5dGVBcnJheXMWBRIEdHlwZRIGb2JqZWN0EgdpbmRpY2VzFQEWAhIEbmFtZRIGaW5kZXgxEgpwcm9wZXJ0aWVzFQEWARIOYnl0ZUFycmF5RmllbGQSA2FzYxIKcHJvcGVydGllcxYCEg5ieXRlQXJyYXlGaWVsZBYDEgR0eXBlEgVhcnJheRIJYnl0ZUFycmF5EwESCG1heEl0ZW1zAyASD2lkZW50aWZpZXJGaWVsZBYFEgR0eXBlEgVhcnJheRIJYnl0ZUFycmF5EwESEGNvbnRlbnRNZWRpYVR5cGUSIWFwcGxpY2F0aW9uL3guZGFzaC5kcHAuaWRlbnRpZmllchIIbWluSXRlbXMDQBIIbWF4SXRlbXMDQBIIcmVxdWlyZWQVARIOYnl0ZUFycmF5RmllbGQSFGFkZGl0aW9uYWxQcm9wZXJ0aWVzEwACQR8nn9fNk4h3AqdYXQeeC/5ocE22Lr1PpNkd+A5UZ9FOwBXVEcO/U8pf1MG1j0i1Dxig9VTz5ggFDF5dBlU0LO9u"
}
3 changes: 3 additions & 0 deletions packages/api/test/mocks/documents_batch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"data": "AgA5Mt8CDjER9k4j2CEtB/703PpP7LxyByK3v+dmpw4HowEBAAAxMiTdZ4q+kWybDD4q7QdT8ZdxFL4w0g3CLNw1saHVAg9pbmRleGVkRG9jdW1lbnQqr34KX3uwQRA+aVogMjLmlFKdzXLoLmikCHYfUvXEYgMB/QAAAYtdNcyNAglmaXJzdE5hbWUSC3VwZGF0ZWROYW1lCGxhc3ROYW1lEghsYXN0TmFtZQFBHx73xSHZqDgJv1lSyZ5TW2ychIpHt59m+II1/4TmcQIcDqfG5qgc2Yr9dg99cD/yHC2EGb/eJ/pjzI5uyDnBYg0="
}
3 changes: 3 additions & 0 deletions packages/api/test/mocks/identity_credit_transfer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"data": "BwD4loS7AXiVfrgeLB9FGBEcEz9O1UaY3rUlSmJvITd5t0RW58h73HXyUAbz28XQrk/7mg86aNP3ZH4rh91CL5BJ/AAEk+ACQR/9yr99QsT2xOqjoEN5snhzOTTQXZun6h6ipr8CDZYSImC/spFBkGELsJzh5ugAUHvaP5LrUKLTvtcEFNg6Suph"
}
3 changes: 3 additions & 0 deletions packages/api/test/mocks/identity_top_up.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"data": "BAAAAMYBAWibBFixOtwYbaffWOj3mg6aK++VPtInXNZl+dJs7dREAQAAAHppdjdMsH47J+8Xpg8XKNhFxEwJZOdqlZrE+qUN6uuQgvbh8+VJzNsFpK/dbUfe3cph+7GkMMKgSU0md7EAAACtQfL826RpgbHNBQRshwksd2loV3Kk5cJD0gtEoZwc2PSzwmk6Vv/2aa+DLyeSZdsTHE3ei8t0Raye9U1By+QipAdP46y9AF4Zn9Ecx0YWaHwOHjTFcitTJvwqaWiqEWLfAwAAAAFomwRYsTrcGG2n31jo95oOmivvlT7SJ1zWZfnSbO3URAEAAABrSDBFAiEAgMXmG1DzOYDMl1+Hj3Tmf0cTaIeDSGVD6yrnkIztjD4CIB7h3iZP/J3z5NxKL9FsWzi1sMZPxh/M7gdlrahV8DNLASED7+kviac33G6RtvdnaeAgLIWHCx+PW0KUTijY0n/zW3v/////Ak5hvAAAAAAAFmoUcx4iv6TeG7eYy0CfTfjPX3MGYpNKjzZKAAAAABl2qRRjgY2sBIRK5QC0VomI/QtTroeb3oisAAAAAACwzhLAcHUAuswDCLz4qdF98XVMQdB3c+8aBl5VvE15tUEghnJ/YQOD4hPqaGHHll/utW9LFOnkADGJD2ehKDUMVlw7VSf7g9c1HRE7XXZG6L/5MUs6zlMJHL1KhS62cogtYw=="
}
3 changes: 3 additions & 0 deletions packages/api/test/mocks/identity_update.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"data": "BgD/esk+xoAEtxmR9bV3edknhiVfCXYiIKlMx8r7krCDqwEBAAMAAAMAACEDRgLoLVDYwGfwQWmheiKsG9fKI9sy+jaz+R/F5/kcz99BH6QHjyT/1QEVq9lnFYn8Qqocd8wFIC/2GJ8xy7xUs9tmXe9K1Lcui6KNfgOD7Dv7/iGn6KBVBr8SJEeYG5wt9sMAAABBIFoOqWIMOrK7mkIoGumFCQpaD1IDZ+FwH69V7ln5hfh1M0Nkn7hHPy6+ZijDzZEh0w/VS2h4UOFg77/JIAINzXo="
}
101 changes: 101 additions & 0 deletions packages/api/test/utils.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
const {describe, it, before} = require('node:test');
const assert = require('node:assert').strict;
const utils = require('../src/utils')
const createIdentityMock = require('./mocks/create_identity.json')
const dataContractCreateMock = require('./mocks/data_contract_create.json')
const documentsBatchMock = require('./mocks/documents_batch.json')
const identityTopUpMock = require('./mocks/identity_top_up.json')
const data_contract_update = require('./mocks/data_contract_update.json')
const identityUpdateMock = require('./mocks/identity_update.json')
const identityCreditTransfer = require('./mocks/identity_credit_transfer.json')
const Dash = require("dash");


describe('Utils', () => {
let client

before(async () => {
client = new Dash.Client()
await client.platform.initialize()
})

describe('decodeStateTransition()', () => {
it('should decode DataContractCreate', async () => {
const decoded = await utils.decodeStateTransition(client, dataContractCreateMock.data)

assert.deepEqual(decoded, {
dataContractId: '4xYD4cASeif5e1auCerLhXR8jvDAwshWUdspk3WiBwhE',
type: 0
});
});

it('should decode DocumentsBatch', async () => {
const decoded = await utils.decodeStateTransition(client, documentsBatchMock.data)

assert.deepEqual(decoded, {
type: 1,
transitions: [
{
action: 1,
createdAt: null,
dataContractId: '3sdL7s2mLtNmczbQWGP6NZQy3HS43UKQHL1YGLDmPXhj',
id: '4K3Kqdb4zsfVUCb6Tc4FjChK9CBU6NNAhQ7f1NMUeyqB',
revision: 3,
updatedAt: new Date("2023-10-23T15:44:48.781Z")
}
]
})
});

it('should decode CreateIdentity', async () => {
const decoded = await utils.decodeStateTransition(client, createIdentityMock.data)

assert.deepEqual(decoded, {
identityId: '7Gw32yK4vhKw926wWmwVDdzQjqxBvXyLK4FbpibYxUwa',
type: 2
});
});

it('should decode IdentityTopUp', async () => {
const decoded = await utils.decodeStateTransition(client, identityTopUpMock.data)

assert.deepEqual(decoded, {
identityId: 'CuB1Qf2ArA1gGFXyp1muQDcKhdMmrx5yAduZWwqHHKji',
type: 3,
amount: 12345678000
});
});

it('should decode DataContractUpdate', async () => {
const decoded = await utils.decodeStateTransition(client, data_contract_update.data)

assert.deepEqual(decoded, {
identityId: 'Dxjkf7du87BbHjiYASdwnCwEhuCbECM6MDiqQY3HHJd9',
dataContractId: '6jcciCBHZPTuoXEGdyakBkaumsyJRHMEJFyZt25emNML',
type: 4,
version: 2
});
});

it('should decode IdentityUpdate', async () => {
const decoded = await utils.decodeStateTransition(client, identityUpdateMock.data)

assert.deepEqual(decoded, {
identityId: 'JCHZE1TDEWJbP9uPCJfv7GneD1y15KiAfda81DLTW1Ce',
type: 5,
revision: 1
});
});

it('should decode IdentityCreditWithdrawal', async () => {
const decoded = await utils.decodeStateTransition(client, identityCreditTransfer.data)

assert.deepEqual(decoded, {
senderId: 'HjPEFAs47nKW31zDRpP42dizumjmNAZJX5aAS2PbZo3k',
recipientId: '5bmapJVccVuNZuEacC2nPBuVkzG7PzzZrJPFFurQhHjv',
amount: 300000,
type: 7
});
});
});
});

0 comments on commit 4218e7e

Please sign in to comment.