Skip to content

Commit

Permalink
Merge pull request #143 from pshenmic/feat/api-tx-result
Browse files Browse the repository at this point in the history
Add transaction fee, status and error message
  • Loading branch information
pshenmic authored Jun 5, 2024
2 parents 73a509a + 4e56c95 commit f34159d
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 21 deletions.
22 changes: 20 additions & 2 deletions packages/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ GET /blocks
---
### Transaction by hash
Get a transaction (state transition) by hash

Status can be either `SUCCESS` or `FAIL`. In case of error tx, message will appear in the `error` field as Base64 string

```
GET /transaction/DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF
Expand All @@ -138,7 +141,10 @@ GET /transaction/DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEE
hash: "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
index: 0,
timestamp: "2024-03-18T10:13:54.150Z",
type: 0
type: 0,
gasUsed: 1337000,
status: "SUCCESS",
error: null
}
```

Expand All @@ -151,6 +157,9 @@ Response codes:
---
### Transactions
Return transaction set paged

Status can be either `SUCCESS` or `FAIL`. In case of error tx, message will appear in the `error` field as Base64 string

```
GET /transactions?=1&limit=10&order=asc
Expand All @@ -168,7 +177,10 @@ GET /transactions?=1&limit=10&order=asc
hash: "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
index: 0,
timestamp: "2024-03-18T10:13:54.150Z",
type: 0
type: 0,
gasUsed: 1337000,
status: "SUCCESS",
error: null
}, ...
]
}
Expand Down Expand Up @@ -419,6 +431,9 @@ Response codes:
---
### Transactions by Identity
Return all transactions made by the given identity

Status can be either `SUCCESS` or `FAIL`. In case of error tx, message will appear in the `error` field as Base64 string

```
GET /identities/GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec/transactions?page=1&limit=10&order=asc
Expand All @@ -437,6 +452,9 @@ GET /identities/GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec/transactions?page=1
type: 0,
data: null,
timestamp: "2024-03-18T10:13:54.150Z",
gasUsed: 1337000,
status: "SUCCESS",
error: null
}, ...
]
}
Expand Down
7 changes: 5 additions & 2 deletions packages/api/src/dao/IdentitiesDAO.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,13 +222,16 @@ module.exports = class IdentitiesDAO {
const toRank = fromRank + limit - 1

const subquery = this.knex('state_transitions')
.select('state_transitions.id as state_transition_id', 'state_transitions.hash as tx_hash', 'state_transitions.index as index',
'state_transitions.type as type', 'state_transitions.block_hash as block_hash')
.select('state_transitions.id as state_transition_id', 'state_transitions.hash as tx_hash',
'state_transitions.index as index', 'state_transitions.type as type', 'state_transitions.block_hash as block_hash',
'state_transitions.gas_used as gas_used', 'state_transitions.status as status', 'state_transitions.error as error'
)
.select(this.knex.raw(`rank() over (order by state_transitions.id ${order}) rank`))
.where('state_transitions.owner', '=', identifier)

const rows = await this.knex.with('with_alias', subquery)
.select('state_transition_id', 'tx_hash', 'index', 'block_hash', 'type', 'rank',
'gas_used', 'status', 'gas_used',
'blocks.timestamp as timestamp', 'blocks.height as block_height')
.select(this.knex('with_alias').count('*').as('total_count'))
.leftJoin('blocks', 'blocks.hash', 'block_hash')
Expand Down
4 changes: 3 additions & 1 deletion packages/api/src/dao/TransactionsDAO.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = class TransactionsDAO {
getTransactionByHash = async (hash) => {
const [row] = await this.knex('state_transitions')
.select('state_transitions.hash as tx_hash', 'state_transitions.data as data',
'state_transitions.gas_used as gas_used', 'state_transitions.status as status', 'state_transitions.error as error',
'state_transitions.type as type', 'state_transitions.index as index', 'blocks.height as block_height',
'blocks.hash as block_hash', 'blocks.timestamp as timestamp')
.where('state_transitions.hash', hash)
Expand All @@ -29,13 +30,14 @@ module.exports = class TransactionsDAO {
const subquery = this.knex('state_transitions')
.select(this.knex('state_transitions').count('hash').as('total_count'), 'state_transitions.hash as tx_hash',
'state_transitions.data as data', 'state_transitions.type as type', 'state_transitions.index as index',
'state_transitions.gas_used as gas_used', 'state_transitions.status as status', 'state_transitions.error as error',
'state_transitions.block_hash as block_hash', 'state_transitions.id as id')
.select(this.knex.raw(`rank() over (order by state_transitions.id ${order}) rank`))
.as('state_transitions')

const rows = await this.knex(subquery)
.select('total_count', 'data', 'type', 'index', 'rank', 'block_hash', 'state_transitions.tx_hash as tx_hash',
'blocks.height as block_height', 'blocks.timestamp as timestamp')
'gas_used', 'status', 'error', 'blocks.height as block_height', 'blocks.timestamp as timestamp')
.leftJoin('blocks', 'blocks.hash', 'block_hash')
.whereBetween('rank', [fromRank, toRank])
.orderBy('state_transitions.id', order)
Expand Down
12 changes: 9 additions & 3 deletions packages/api/src/models/Transaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,25 @@ module.exports = class Transaction {
type
data
timestamp
gasUsed
status
error

constructor (hash, index, blockHash, blockHeight, type, data, timestamp) {
constructor (hash, index, blockHash, blockHeight, type, data, timestamp, gasUsed, status, error) {
this.hash = hash ?? null
this.index = index ?? null
this.blockHash = blockHash ?? null
this.blockHeight = blockHeight ?? null
this.type = type ?? null
this.data = data ?? null
this.timestamp = timestamp ?? null
this.gasUsed = gasUsed ?? null
this.status = status ?? null
this.error = error ?? null
}

// eslint-disable-next-line camelcase
static fromRow ({ tx_hash, index, block_hash, block_height, type, data, timestamp }) {
return new Transaction(tx_hash, index, block_hash, block_height, type, data, timestamp)
static fromRow ({ tx_hash, index, block_hash, block_height, type, data, timestamp, gas_used, status, error }) {
return new Transaction(tx_hash, index, block_hash, block_height, type, data, timestamp, parseInt(gas_used), status, error)
}
}
20 changes: 16 additions & 4 deletions packages/api/test/integration/identities.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,10 @@ describe('Identities routes', () => {
blockHeight: _transaction.block.height,
type: i === 0 ? StateTransitionEnum.IDENTITY_CREATE : StateTransitionEnum.DOCUMENTS_BATCH,
data: null,
timestamp: _transaction.block.timestamp.toISOString()
timestamp: _transaction.block.timestamp.toISOString(),
gasUsed: _transaction.transaction.gas_used,
status: _transaction.transaction.status,
error: _transaction.transaction.error
}))

assert.deepEqual(body.resultSet, expectedTransactions)
Expand Down Expand Up @@ -795,7 +798,10 @@ describe('Identities routes', () => {
blockHeight: _transaction.block.height,
type: StateTransitionEnum.DOCUMENTS_BATCH,
data: null,
timestamp: _transaction.block.timestamp.toISOString()
timestamp: _transaction.block.timestamp.toISOString(),
gasUsed: _transaction.transaction.gas_used,
status: _transaction.transaction.status,
error: _transaction.transaction.error
}))

assert.deepEqual(body.resultSet, expectedTransactions)
Expand Down Expand Up @@ -835,7 +841,10 @@ describe('Identities routes', () => {
blockHeight: _transaction.block.height,
type: StateTransitionEnum.DOCUMENTS_BATCH,
data: null,
timestamp: _transaction.block.timestamp.toISOString()
timestamp: _transaction.block.timestamp.toISOString(),
gasUsed: _transaction.transaction.gas_used,
status: _transaction.transaction.status,
error: _transaction.transaction.error
}))

assert.deepEqual(body.resultSet, expectedTransactions)
Expand Down Expand Up @@ -875,7 +884,10 @@ describe('Identities routes', () => {
blockHeight: _transaction.block.height,
type: StateTransitionEnum.DOCUMENTS_BATCH,
data: null,
timestamp: _transaction.block.timestamp.toISOString()
timestamp: _transaction.block.timestamp.toISOString(),
gasUsed: _transaction.transaction.gas_used,
status: _transaction.transaction.status,
error: _transaction.transaction.error
}))

assert.deepEqual(body.resultSet, expectedTransactions)
Expand Down
5 changes: 4 additions & 1 deletion packages/api/test/integration/main.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,10 @@ describe('Other routes', () => {
blockHeight: block.height,
type: dataContractTransaction.type,
data: JSON.stringify(dataContractTransaction.data),
timestamp: block.timestamp.toISOString()
timestamp: block.timestamp.toISOString(),
gasUsed: dataContractTransaction.gas_used,
status: dataContractTransaction.status,
error: dataContractTransaction.error
}

assert.deepEqual({ transaction: expectedTransaction }, body)
Expand Down
60 changes: 54 additions & 6 deletions packages/api/test/integration/transactions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,18 @@ describe('Transaction routes', () => {

transactions = [{ transaction: identity.transaction, block }]

for (let i = 1; i < 30; i++) {
// error tx
const errorTx = await fixtures.transaction(knex, {
block_hash: block.hash,
data: '{}',
type: StateTransitionEnum.DOCUMENTS_BATCH,
owner: identity.identifier,
error: 'fake_err',
status: 'FAIL'
})
transactions.push({ transaction: errorTx, block })

for (let i = 2; i < 30; i++) {
const block = await fixtures.block(knex, {
height: i + 1, timestamp: new Date(startDate.getTime() + i * 1000 * 60)
})
Expand Down Expand Up @@ -81,7 +92,32 @@ describe('Transaction routes', () => {
hash: transaction.transaction.hash,
index: transaction.transaction.index,
timestamp: transaction.block.timestamp.toISOString(),
type: transaction.transaction.type
type: transaction.transaction.type,
gasUsed: transaction.transaction.gas_used,
status: transaction.transaction.status,
error: transaction.transaction.error
}

assert.deepEqual(expectedTransaction, body)
})

it('should error transaction', async () => {
const [, transaction] = transactions
const { body } = await client.get(`/transaction/${transaction.transaction.hash}`)
.expect(200)
.expect('Content-Type', 'application/json; charset=utf-8')

const expectedTransaction = {
blockHash: transaction.block.hash,
blockHeight: transaction.block.height,
data: '{}',
hash: transaction.transaction.hash,
index: transaction.transaction.index,
timestamp: transaction.block.timestamp.toISOString(),
type: transaction.transaction.type,
gasUsed: 0,
status: 'FAIL',
error: 'fake_err'
}

assert.deepEqual(expectedTransaction, body)
Expand Down Expand Up @@ -114,7 +150,10 @@ describe('Transaction routes', () => {
hash: transaction.transaction.hash,
index: transaction.transaction.index,
timestamp: transaction.block.timestamp.toISOString(),
type: transaction.transaction.type
type: transaction.transaction.type,
gasUsed: transaction.transaction.gas_used,
status: transaction.transaction.status,
error: transaction.transaction.error
}))

assert.deepEqual(expectedTransactions, body.resultSet)
Expand All @@ -140,7 +179,10 @@ describe('Transaction routes', () => {
hash: transaction.transaction.hash,
index: transaction.transaction.index,
timestamp: transaction.block.timestamp.toISOString(),
type: transaction.transaction.type
type: transaction.transaction.type,
gasUsed: transaction.transaction.gas_used,
status: transaction.transaction.status,
error: transaction.transaction.error
}))

assert.deepEqual(expectedTransactions, body.resultSet)
Expand All @@ -166,7 +208,10 @@ describe('Transaction routes', () => {
hash: transaction.transaction.hash,
index: transaction.transaction.index,
timestamp: transaction.block.timestamp.toISOString(),
type: transaction.transaction.type
type: transaction.transaction.type,
gasUsed: transaction.transaction.gas_used,
status: transaction.transaction.status,
error: transaction.transaction.error
}))

assert.deepEqual(expectedTransactions, body.resultSet)
Expand All @@ -192,7 +237,10 @@ describe('Transaction routes', () => {
hash: transaction.transaction.hash,
index: transaction.transaction.index,
timestamp: transaction.block.timestamp.toISOString(),
type: transaction.transaction.type
type: transaction.transaction.type,
gasUsed: transaction.transaction.gas_used,
status: transaction.transaction.status,
error: transaction.transaction.error
}))

assert.deepEqual(expectedTransactions, body.resultSet)
Expand Down
22 changes: 20 additions & 2 deletions packages/frontend/src/app/api/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ GET /blocks
---
### Transaction by hash
Get a transaction (state transition) by hash

Status can be either `SUCCESS` or `FAIL`. In case of error tx, message will appear in the `error` field as Base64 string

```
GET /transaction/DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF
Expand All @@ -107,7 +110,10 @@ GET /transaction/DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEE
hash: "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
index: 0,
timestamp: "2024-03-18T10:13:54.150Z",
type: 0
type: 0,
gasUsed: 1337000,
status: "SUCCESS",
error: null
}
```

Expand All @@ -120,6 +126,9 @@ Response codes:
---
### Transactions
Return transaction set paged

Status can be either `SUCCESS` or `FAIL`. In case of error tx, message will appear in the `error` field as Base64 string

```
GET /transactions?=1&limit=10&order=asc
Expand All @@ -137,7 +146,10 @@ GET /transactions?=1&limit=10&order=asc
hash: "DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
index: 0,
timestamp: "2024-03-18T10:13:54.150Z",
type: 0
type: 0,
gasUsed: 1337000,
status: "SUCCESS",
error: null
}, ...
]
}
Expand Down Expand Up @@ -388,6 +400,9 @@ Response codes:
---
### Transactions by Identity
Return all transactions made by the given identity

Status can be either `SUCCESS` or `FAIL`. In case of error tx, message will appear in the `error` field as Base64 string

```
GET /identities/GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec/transactions?page=1&limit=10&order=asc
Expand All @@ -406,6 +421,9 @@ GET /identities/GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec/transactions?page=1
type: 0,
data: null,
timestamp: "2024-03-18T10:13:54.150Z",
gasUsed: 1337000,
status: "SUCCESS",
error: null
}, ...
]
}
Expand Down

0 comments on commit f34159d

Please sign in to comment.