Skip to content

Commit

Permalink
Merge pull request #3 from taraldefi/feat/chainhooks
Browse files Browse the repository at this point in the history
feat(chainhook): add chainhooks implementation
  • Loading branch information
dorucioclea authored Jul 18, 2023
2 parents 4cd4b32 + ef7645f commit abcf336
Show file tree
Hide file tree
Showing 178 changed files with 29,641 additions and 18 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -399,4 +399,6 @@ FodyWeavers.xsd
**/settings/Mainnet.toml
**/settings/Testnet.toml
.cache/**
history.txt
history.txt

.chainhook-subscriber/node_modules/*
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,11 @@ The contract leverages traits (.sip009-nft-trait.nft-trait and .sip010-ft-trait.

In addition to that, the nft marketplace showcases some best practices such as `ownership management` and `separation of contract logic from data`

Separation of contract logic and data is extremely important in the case of versioning and upgreadability. In case we upgrade the marketplace contract, we do not need to do data migration.
Separation of contract logic and data is extremely important in the case of versioning and upgreadability. In case we upgrade the marketplace contract, we do not need to do data migration.


## Tests

* Run normal tests with `clarinet test`

* Run chainhook tests with `clarinet test --chainhooks ./chainhooks/marketplace.chainhook.yaml ./tests_chainhook/integration_test.ts`
1 change: 1 addition & 0 deletions chainhook-consumer/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
API_KEY=api-key-1,api-key-2
24 changes: 24 additions & 0 deletions chainhook-consumer/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};
35 changes: 35 additions & 0 deletions chainhook-consumer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# compiled output
/dist
/node_modules

# Logs
logs
*.log
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# OS
.DS_Store

# Tests
/coverage
/.nyc_output

# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace

# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
5 changes: 5 additions & 0 deletions chainhook-consumer/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 200
}
6 changes: 6 additions & 0 deletions chainhook-consumer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Start the application

```bash
$ yarn install
$ yarn start:dev
```
4 changes: 4 additions & 0 deletions chainhook-consumer/nest-cli.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"collection": "@nestjs/schematics",
"sourceRoot": "src"
}
94 changes: 94 additions & 0 deletions chainhook-consumer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
"name": "nest-auth-apikey-jwt",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^10.0.4",
"@nestjs/config": "^2.1.0",
"@nestjs/core": "^10.0.4",
"@nestjs/jwt": "^8.0.1",
"@nestjs/mapped-types": "*",
"@nestjs/microservices": "^10.0.4",
"@nestjs/passport": "^8.2.1",
"@nestjs/platform-express": "^10.0.4",
"@stacks/transactions": "^6.5.4",
"@types/lodash": "^4.14.195",
"@types/passport-strategy": "^0.2.35",
"amqp-connection-manager": "^4.1.13",
"amqplib": "^0.10.3",
"lodash": "^4.17.21",
"passport": "^0.6.0",
"passport-headerapikey": "^1.2.2",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"passport-strategy": "^1.0.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0"
},
"devDependencies": {
"@nestjs/cli": "^8.0.0",
"@nestjs/schematics": "^8.0.0",
"@nestjs/testing": "^8.0.0",
"@types/express": "^4.17.13",
"@types/jest": "27.4.1",
"@types/node": "^16.0.0",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^27.2.5",
"lint-staged": "^13.0.1",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"ts-jest": "^27.0.3",
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"tsconfig-paths": "^3.10.1",
"typescript": "^4.3.5"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
},
"lint-staged": {
"**/*.{ts,tsx}": [
"yarn format",
"yarn lint"
]
}
}
22 changes: 22 additions & 0 deletions chainhook-consumer/src/app.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';

describe('AppController', () => {
let appController: AppController;

beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [AppController],
providers: [AppService],
}).compile();

appController = app.get<AppController>(AppController);
});

describe('root', () => {
it('should return "Hello World!"', () => {
expect(appController.getHello()).toBe('Hello World!');
});
});
});
52 changes: 52 additions & 0 deletions chainhook-consumer/src/app.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common';
import { ChainhookResponse } from './chainhook/ChainhookResponse';
import { Event } from './chainhook/Event';
import { cvToValue, deserializeCV } from "@stacks/transactions";
import { AuctionPublisherService } from './rabbtmq/auction.service';

// @UseGuards(ApiKeyAuthGuard)
@Controller()
export class AppController {
constructor(private readonly auctionPublishingService: AuctionPublisherService) {}

@Get()
getHello(): string {
return 'Hello World!';
}


@Post('chainhook')
async chainhook(@Body() body: any): Promise<void> {
const chainhook = body as ChainhookResponse;

const printEvents: Event[] = [];

const transactions = chainhook.apply.map(apply => apply.transactions).reduce(function(a, b){ return a.concat(b); }, []);;

for (const transaction of transactions) {
if (transaction.metadata.success) {
//
// check the events of the metadata

const transactionPrintEvents = (transaction.metadata.receipt.events || [])
.filter(event => event.type === 'SmartContractEvent' && event.data.topic == "print");

printEvents.push(...transactionPrintEvents);
}
}

for (const printEvent of printEvents) {
const hexData = printEvent.data.raw_value.replace('0x', '');
const printPayloadCV = deserializeCV(Buffer.from(hexData, "hex"));
const printPayload = cvToValue(printPayloadCV);

console.log(JSON.stringify(printPayload));

console.log('---------------------------------------');

await this.auctionPublishingService.publishMessage('auction_event', JSON.stringify(printPayload));

console.log('Published message');
}
}
}
21 changes: 21 additions & 0 deletions chainhook-consumer/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AuthModule } from './auth/auth.module';
import { ClientsModule } from '@nestjs/microservices';
import { rabbitMQServiceOptions } from './rabbtmq/constants';
import { AuctionPublisherService } from './rabbtmq/auction.service';

@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
AuthModule,
ClientsModule.register([
rabbitMQServiceOptions as any
]),
],
controllers: [AppController],
providers: [AppService, AuctionPublisherService],
})
export class AppModule {}
8 changes: 8 additions & 0 deletions chainhook-consumer/src/app.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
12 changes: 12 additions & 0 deletions chainhook-consumer/src/auth/auth.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { StaticBearerStrategy } from './strategy/static-bearer.strategy';

@Module({
imports: [
PassportModule
],
providers: [StaticBearerStrategy],
exports: [],
})
export class AuthModule {}
5 changes: 5 additions & 0 deletions chainhook-consumer/src/auth/guard/apikey-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class ApiKeyAuthGuard extends AuthGuard('static-bearer') {}
5 changes: 5 additions & 0 deletions chainhook-consumer/src/auth/guard/jwt-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
5 changes: 5 additions & 0 deletions chainhook-consumer/src/auth/guard/local-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {}
Loading

0 comments on commit abcf336

Please sign in to comment.