Skip to content

Commit

Permalink
Full support of sign transaction schema
Browse files Browse the repository at this point in the history
  • Loading branch information
wcalderipe committed Jan 17, 2024
1 parent ad6ef6f commit 5af2884
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 75 deletions.
60 changes: 56 additions & 4 deletions apps/orchestration/src/policy-engine/__test__/e2e/facade.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
AUTHORIZATION_REQUEST_PROCESSING_QUEUE,
REQUEST_HEADER_ORG_ID
} from '@app/orchestration/orchestration.constant'
import { Action, AuthorizationRequest } from '@app/orchestration/policy-engine/core/type/domain.type'
import { Action, AuthorizationRequest, TransactionType } from '@app/orchestration/policy-engine/core/type/domain.type'
import { AuthorizationRequestRepository } from '@app/orchestration/policy-engine/persistence/repository/authorization-request.repository'
import { PolicyEngineModule } from '@app/orchestration/policy-engine/policy-engine.module'
import { PersistenceModule } from '@app/orchestration/shared/module/persistence/persistence.module'
Expand All @@ -16,7 +16,7 @@ import { Test, TestingModule } from '@nestjs/testing'
import { AuthorizationRequestStatus, Organization } from '@prisma/client/orchestration'
import { Queue } from 'bull'
import request from 'supertest'
import { hashMessage } from 'viem'
import { hashMessage, stringToHex } from 'viem'

const EVALUATIONS_ENDPOINT = '/policy-engine/evaluations'

Expand Down Expand Up @@ -116,10 +116,62 @@ describe('Policy Engine Cluster Facade', () => {

it('evaluates a sign transaction authorization request', async () => {
const signTransactionRequest = {
chainId: 1,
data: '0x',
from: '0xaaa8ee1cbaa1856f4550c6fc24abb16c5c9b2a43',
gas: '5000',
nonce: 0,
to: '0xbbb7be636c3ad8cf9d08ba8bdba4abd2ef29bd23',
data: '0x',
gas: '5000'
type: TransactionType.EIP1559,
value: '0x',
accessList: [
{
address: '0xccc1472fce4ec74a1e3f9653776acfc790cd0743',
storageKeys: [stringToHex('storage-key-one'), stringToHex('storage-key-two')]
}
]
}
const payload = {
action: Action.SIGN_TRANSACTION,
hash: hashMessage(JSON.stringify(signTransactionRequest)),
request: signTransactionRequest,
authentication: {
signature: {
hash: 'string'
}
},
approval: {
signatures: [
{
hash: 'string'
}
]
}
}

const { status, body } = await request(app.getHttpServer())
.post(EVALUATIONS_ENDPOINT)
.set(REQUEST_HEADER_ORG_ID, org.id)
.send(payload)

expect(body).toMatchObject({
id: expect.any(String),
status: AuthorizationRequestStatus.CREATED,
idempotencyKey: null,
action: payload.action,
hash: payload.hash,
request: payload.request,
createdAt: expect.any(String),
updatedAt: expect.any(String)
})
expect(status).toEqual(HttpStatus.OK)
})

it('evaluates a partial sign transaction authorization request', async () => {
const signTransactionRequest = {
from: '0xaaa8ee1cbaa1856f4550c6fc24abb16c5c9b2a43',
nonce: 0,
chainId: 1
}
const payload = {
action: Action.SIGN_TRANSACTION,
Expand Down
35 changes: 19 additions & 16 deletions apps/orchestration/src/policy-engine/core/type/domain.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,30 @@ export type SharedAuthorizationRequest = {

export type Hex = `0x${string}`
export type Address = `0x${string}`
export type AccessList = { address: Address; storageKeys: Hex[] }[]
export type AccessList = {
address: Address
storageKeys: Hex[]
}[]

/**
* @see https://viem.sh/docs/glossary/types#transactiontype
*/
export enum TransactionType {
LEGACY = 'legacy',
EIP2930 = 'eip2930',
EIP1559 = 'eip1559'
}

// Original transaction request
//
// export type TransactionRequest<TQuantity = Hex, TIndex = number, TTransactionType = '2'> = {
// data?: Hex
// from: Address
// to?: Address | null
// gas?: TQuantity
// nonce: TIndex
// value?: TQuantity
// chainId: string | null
// accessList?: AccessList
// type?: TTransactionType
// }
// Temporary lite version
export type TransactionRequest = {
data?: Hex
chainId: number
from: Address
nonce: number
accessList?: AccessList
data?: Hex
gas?: bigint
to?: Address | null
type?: `${TransactionType}`
value?: Hex
}

export type SignTransactionAuthorizationRequest = SharedAuthorizationRequest & {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Action, Address, Hex } from '@app/orchestration/policy-engine/core/type/domain.type'
import { Action } from '@app/orchestration/policy-engine/core/type/domain.type'
import { SignMessageRequestDto } from '@app/orchestration/policy-engine/http/rest/dto/sign-message-request.dto'
import { SignTransactionRequestDto } from '@app/orchestration/policy-engine/http/rest/dto/sign-transaction-request.dto'
import { SignatureDto } from '@app/orchestration/policy-engine/http/rest/dto/signature.dto'
import { ApiExtraModels, ApiProperty, getSchemaPath } from '@nestjs/swagger'
import { Transform, Type } from 'class-transformer'
import { IsDefined, IsEnum, IsEthereumAddress, IsString, Validate, ValidateNested } from 'class-validator'
import { Type } from 'class-transformer'
import { IsDefined, IsEnum, IsString, Validate, ValidateNested } from 'class-validator'
import { RequestHash } from './validator/request-hash.validator'

class AuthenticationDto {
Expand All @@ -18,48 +20,6 @@ class ApprovalDto {
signatures: SignatureDto[]
}

export class SignTransactionRequestDto {
@IsString()
@IsDefined()
@IsEthereumAddress()
@Transform(({ value }) => value.toLowerCase())
@ApiProperty({
required: true,
format: 'EthereumAddress'
})
from: Address

@IsString()
@IsEthereumAddress()
@Transform(({ value }) => value.toLowerCase())
@ApiProperty({
format: 'EthereumAddress'
})
to?: Address | null

@IsString()
@ApiProperty({
type: 'string',
format: 'Hexadecimal'
})
data?: Hex

@Transform(({ value }) => BigInt(value))
@ApiProperty({
type: 'string'
})
gas?: bigint
}

export class SignMessageRequestDto {
@IsString()
@IsDefined()
@ApiProperty({
required: true
})
message: string
}

@ApiExtraModels(SignTransactionRequestDto, SignMessageRequestDto)
export class AuthorizationRequestDto {
@IsEnum(Action)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Action, AuthorizationRequestStatus } from '@app/orchestration/policy-engine/core/type/domain.type'
import {
SignMessageRequestDto,
SignTransactionRequestDto
} from '@app/orchestration/policy-engine/http/rest/dto/authorization-request.dto'
import { EvaluationDto } from '@app/orchestration/policy-engine/http/rest/dto/evaluation.dto'
import { ApiProperty, getSchemaPath } from '@nestjs/swagger'
import { SignMessageRequestDto } from '@app/orchestration/policy-engine/http/rest/dto/sign-message-request.dto'
import { SignTransactionRequestDto } from '@app/orchestration/policy-engine/http/rest/dto/sign-transaction-request.dto'
import { ApiExtraModels, ApiProperty, getSchemaPath } from '@nestjs/swagger'
import { Transform, Type } from 'class-transformer'
import { IsString } from 'class-validator'
import { IsOptional, IsString } from 'class-validator'

/**
* The transformer function in the "@Transformer" decorator for bigint
Expand All @@ -19,6 +17,7 @@ import { IsString } from 'class-validator'
*/
class SignTransactionResponseDto extends SignTransactionRequestDto {
@IsString()
@IsOptional()
@Transform(({ value }) => value.toString())
@ApiProperty({
type: 'string'
Expand All @@ -29,6 +28,7 @@ class SignTransactionResponseDto extends SignTransactionRequestDto {
// Just for keeping consistency on the naming.
class SignMessageResponseDto extends SignMessageRequestDto {}

@ApiExtraModels(SignTransactionResponseDto, SignMessageResponseDto)
export class AuthorizationResponseDto {
@ApiProperty()
id: string
Expand All @@ -40,6 +40,11 @@ export class AuthorizationResponseDto {
initiatorId: string

@IsString()
@ApiProperty({
required: false,
type: 'string',
nullable: true
})
idempotencyKey?: string | null

@ApiProperty({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ApiProperty } from '@nestjs/swagger'
import { IsDefined, IsString } from 'class-validator'

export class SignMessageRequestDto {
@IsString()
@IsDefined()
@ApiProperty({
required: true,
type: 'string'
})
message: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { Address, Hex, TransactionType } from '@app/orchestration/policy-engine/core/type/domain.type'
import { ApiProperty } from '@nestjs/swagger'
import { Transform } from 'class-transformer'
import {
IsDefined,
IsEnum,
IsEthereumAddress,
IsInt,
IsNumber,
IsOptional,
IsString,
Min,
ValidateNested
} from 'class-validator'

class AccessListDto {
@IsString()
@IsDefined()
@IsEthereumAddress()
@Transform(({ value }) => value.toLowerCase())
@ApiProperty({
format: 'Address',
required: true,
type: 'string'
})
address: Address

@IsString()
@ApiProperty({
format: 'Hexadecimal',
isArray: true,
required: true,
type: 'string'
})
storageKeys: Hex[]
}

export class SignTransactionRequestDto {
@IsInt()
@Min(1)
@ApiProperty({
minimum: 1
})
chainId: number

@IsString()
@IsDefined()
@IsEthereumAddress()
@Transform(({ value }) => value.toLowerCase())
@ApiProperty({
format: 'address',
type: 'string'
})
from: Address

@IsNumber()
@Min(0)
@ApiProperty({
minimum: 0
})
nonce: number

@IsOptional()
@ValidateNested()
@ApiProperty({
isArray: true,
required: false,
type: AccessListDto
})
accessList?: AccessListDto[]

@IsString()
@IsOptional()
@ApiProperty({
format: 'hexadecimal',
required: false,
type: 'string'
})
data?: Hex

@IsOptional()
@Transform(({ value }) => BigInt(value))
@ApiProperty({
format: 'bigint',
required: false,
type: 'string'
})
gas?: bigint

@IsString()
@IsEthereumAddress()
@IsOptional()
@Transform(({ value }) => value.toLowerCase())
@ApiProperty({
format: 'address',
required: false,
type: 'string'
})
to?: Address | null

@IsEnum(TransactionType)
@IsOptional()
@ApiProperty({
enum: TransactionType,
required: false
})
type?: `${TransactionType}`

@IsString()
@IsOptional()
@ApiProperty({
format: 'hexadecimal',
required: false,
type: 'string'
})
value?: Hex
}
9 changes: 7 additions & 2 deletions apps/orchestration/src/policy-engine/http/rest/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@ export const toCreateAuthorizationRequest = (
...shared,
action: Action.SIGN_TRANSACTION,
request: {
accessList: dto.request.accessList,
chainId: dto.request.chainId,
data: dto.request.data,
from: dto.request.from,
gas: dto.request.gas,
nonce: dto.request.nonce,
to: dto.request.to,
data: dto.request.data,
gas: dto.request.gas
type: dto.request.type,
value: dto.request.value
}
}
}
Loading

0 comments on commit 5af2884

Please sign in to comment.