Skip to content

Commit

Permalink
Merge pull request #313 from pshenmic/feat/withdrawals-dapi
Browse files Browse the repository at this point in the history
Withdrawals data from dapi
  • Loading branch information
owl352 authored Nov 18, 2024
2 parents 6c19f6f + 273e564 commit 999face
Show file tree
Hide file tree
Showing 10 changed files with 507 additions and 11 deletions.
53 changes: 53 additions & 0 deletions packages/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,60 @@ Response codes:
200: OK
500: Internal Server Error
```
---
### Identity Withdrawals
Return all withdrawals for identity

_Note: this request does not contain any pagination data in the response_

* `limit` cannot be more then 100
```
GET /identity/A1rgGVjRGuznRThdAA316VEEpKuVQ7mV8mBK1BFJvXnb/withdrawals?limit=5
[
{
"timestamp": 1729096625509,
"sender": "A1rgGVjRGuznRThdAA316VEEpKuVQ7mV8mBK1BFJvXnb",
"id": "95eiiqMotMvH23f6cv3BPC4ykcHFWTy2g3baCTWZANAs",
"amount": 200000,
"status": 3
},
{
"timestamp": 1729096140465,
"sender": "A1rgGVjRGuznRThdAA316VEEpKuVQ7mV8mBK1BFJvXnb",
"id": "DJzb8nj7JTHwnvAGEGhyFc5hHLFa5Es9WFAyS4HhhNeF",
"amount": 200000,
"status": 3
},
{
"timestamp": 1729096636318,
"sender": "A1rgGVjRGuznRThdAA316VEEpKuVQ7mV8mBK1BFJvXnb",
"id": "E4gbWCQgqrz9DVrzCeDKhr4PVsfp6CeL5DUAYndRVWdk",
"amount": 200000,
"status": 3
},
{
"timestamp": 1729096795042,
"sender": "A1rgGVjRGuznRThdAA316VEEpKuVQ7mV8mBK1BFJvXnb",
"id": "FouX2qY8Eaxj5rSBrH9uxbhAM16ozrUP4sJwdo9pL7Cr",
"amount": 200000,
"status": 3
},
{
"timestamp": 1729097247874,
"sender": "A1rgGVjRGuznRThdAA316VEEpKuVQ7mV8mBK1BFJvXnb",
"id": "9VEpb2aJRnCxfi3LjFXWa1zshkBPfzzHHh5yqEkgqw1t",
"amount": 200000,
"status": 3
}
]
```
Response codes:
```
200: OK
500: Internal Server Error
```
---
### Data contracts by Identity
Return all data contracts by the given identity

Expand Down
141 changes: 141 additions & 0 deletions packages/api/data_contracts/withdrawals.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
{
"version": 0,
"ownerId": "11111111111111111111111111111111",
"id": "4fJLR2GYTPFdomuTVvNy3VRrvWgvkKPzqehEBpNf2nk6",
"$format_version": "0",
"documentSchemas": {
"withdrawal": {
"type": "object",
"indices": [
{
"name": "identityStatus",
"unique": false,
"properties": [
{
"$ownerId": "asc"
},
{
"status": "asc"
},
{
"$createdAt": "asc"
}
]
},
{
"name": "identityRecent",
"unique": false,
"properties": [
{
"$ownerId": "asc"
},
{
"$updatedAt": "asc"
},
{
"status": "asc"
}
]
},
{
"name": "pooling",
"unique": false,
"properties": [
{
"status": "asc"
},
{
"pooling": "asc"
},
{
"coreFeePerByte": "asc"
},
{
"$updatedAt": "asc"
}
]
},
{
"name": "transaction",
"unique": false,
"properties": [
{
"status": "asc"
},
{
"transactionIndex": "asc"
}
]
}
],
"required": [
"$createdAt",
"$updatedAt",
"amount",
"coreFeePerByte",
"pooling",
"outputScript",
"status"
],
"properties": {
"amount": {
"type": "integer",
"minimum": 1000,
"position": 2,
"description": "The amount to be withdrawn"
},
"status": {
"enum": [
0,
1,
2,
3,
4
],
"type": "integer",
"position": 6,
"description": "0 - Pending, 1 - Signed, 2 - Broadcasted, 3 - Complete, 4 - Expired"
},
"pooling": {
"enum": [
0,
1,
2
],
"type": "integer",
"position": 4,
"description": "This indicated the level at which Platform should try to pool this transaction"
},
"outputScript": {
"type": "array",
"maxItems": 25,
"minItems": 23,
"position": 5,
"byteArray": true
},
"coreFeePerByte": {
"type": "integer",
"maximum": 4294967295,
"minimum": 1,
"position": 3,
"description": "This is the fee that you are willing to spend for this transaction in Duffs/Byte"
},
"transactionIndex": {
"type": "integer",
"minimum": 1,
"position": 0,
"description": "Sequential index of asset unlock (withdrawal) transaction. Populated when a withdrawal pooled into withdrawal transaction"
},
"transactionSignHeight": {
"type": "integer",
"minimum": 1,
"position": 1,
"description": "The Core height on which transaction was signed"
}
},
"description": "Withdrawal document to track underlying withdrawal transactions. Withdrawals should be created with IdentityWithdrawalTransition",
"additionalProperties": false,
"creationRestrictionMode": 2
}
}
}
19 changes: 19 additions & 0 deletions packages/api/src/DAPI.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const Withdrawal = require('./models/Withdrawal')
const { Identifier } = require('dash').PlatformProtocol

class DAPI {
Expand All @@ -24,6 +25,24 @@ class DAPI {
return epochsInfo
}

async getDocuments (type, dataContractObject, identifier, limit) {
const dataContract = await this.dpp.dataContract.createFromObject(dataContractObject)

const { documents } = await this.dapi.platform.getDocuments(Identifier.from(dataContractObject.id), type, {
limit,
where: [
['$ownerId', '=', Identifier.from(identifier)]
]
})

return documents.map(
(document) =>
Withdrawal.fromRaw(
this.dpp.document.createExtendedDocumentFromDocumentBuffer(document, type, dataContract).toJSON()
)
)
}

/**
* Fetch the version upgrade votes status
* @typedef {getContestedState}
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 @@ -3,6 +3,7 @@ const TenderdashRPC = require('./tenderdashRpc')
let genesisTime

module.exports = {
WITHDRAWAL_CONTRACT_TYPE: 'withdrawal',
EPOCH_CHANGE_TIME: Number(process.env.EPOCH_CHANGE_TIME),
TCP_CONNECT_TIMEOUT: Number(process.env.TCP_CONNECT_TIMEOUT),
DPNS_CONTRACT: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec',
Expand Down
28 changes: 18 additions & 10 deletions packages/api/src/controllers/IdentitiesController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const IdentitiesDAO = require('../dao/IdentitiesDAO')
const { IDENTITY_CREDIT_WITHDRAWAL } = require('../enums/StateTransitionEnum')
const { WITHDRAWAL_CONTRACT_TYPE } = require('../constants')
const WithdrawalsContract = require('../../data_contracts/withdrawals.json')

class IdentitiesController {
constructor (knex, dapi) {
Expand Down Expand Up @@ -77,17 +78,24 @@ class IdentitiesController {

getWithdrawalsByIdentity = async (request, response) => {
const { identifier } = request.params
const { page = 1, limit = 10, order = 'asc' } = request.query
const { limit = 100 } = request.query

const documents = await this.dapi.getDocuments(WITHDRAWAL_CONTRACT_TYPE, WithdrawalsContract, identifier, limit)

const timestamps = documents.map(document => new Date(document.timestamp).toISOString())

const withdrawals = await this.identitiesDAO.getTransfersByIdentity(
identifier,
Number(page ?? 1),
Number(limit ?? 10),
order ?? 'asc',
IDENTITY_CREDIT_WITHDRAWAL
)
const txHashes = await this.identitiesDAO.getIdentityWithdrawalsByTimestamps(identifier, timestamps)

if (documents.length === 0) {
return response.status(404).send({ message: 'not found' })
}

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

Expand Down
13 changes: 13 additions & 0 deletions packages/api/src/dao/IdentitiesDAO.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Transaction = require('../models/Transaction')
const Document = require('../models/Document')
const DataContract = require('../models/DataContract')
const PaginatedResultSet = require('../models/PaginatedResultSet')
const { IDENTITY_CREDIT_WITHDRAWAL } = require('../enums/StateTransitionEnum')
const { getAliasInfo } = require('../utils')
const { base58 } = require('@scure/base')

Expand Down Expand Up @@ -353,4 +354,16 @@ module.exports = class IdentitiesDAO {

return new PaginatedResultSet(rows.map(row => Transfer.fromRow(row)), page, limit, totalCount)
}

getIdentityWithdrawalsByTimestamps = async (identifier, timestamps = []) => {
return this.knex('state_transitions')
.select('state_transitions.hash', 'blocks.timestamp as timestamp')
.whereIn(
'blocks.timestamp',
timestamps
)
.andWhere('owner', identifier)
.andWhere('type', IDENTITY_CREDIT_WITHDRAWAL)
.leftJoin('blocks', 'block_hash', 'blocks.hash')
}
}
21 changes: 21 additions & 0 deletions packages/api/src/models/Withdrawal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = class Withdrawal {
timestamp
hash
sender
id
amount
status

constructor (timestamp, hash, sender, id, amount, status) {
this.timestamp = timestamp ?? null
this.hash = hash ?? null
this.sender = sender ?? null
this.id = id ?? null
this.amount = amount ?? null
this.status = status ?? null
}

static fromRaw (data = {}) {
return new Withdrawal(data.$createdAt, null, data.$ownerId, data.$id, data.amount, data.status)
}
}
1 change: 0 additions & 1 deletion packages/api/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ module.exports = ({
method: 'GET',
handler: identitiesController.getWithdrawalsByIdentity,
schema: {
querystring: { $ref: 'paginationOptions#' },
params: {
type: 'object',
properties: {
Expand Down
Loading

0 comments on commit 999face

Please sign in to comment.