Skip to content

Commit

Permalink
feat: 🎸 add address and nonce to tx model
Browse files Browse the repository at this point in the history
also adds offline request model, and revert script to run migrations
down
  • Loading branch information
polymath-eric committed Jan 16, 2024
1 parent d665053 commit aaf685b
Show file tree
Hide file tree
Showing 15 changed files with 103 additions and 20 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"postgres:dev:reset": "yarn postgres:dev down postgres --volumes && yarn postgres:dev:start",
"postgres:dev:migration:generate": "source ./postgres.dev.config && yarn postgres migration:generate",
"postgres:dev:migration:run": "source ./postgres.dev.config && yarn postgres migration:run",
"postgres:dev:migration:revert": "source ./postgres.dev.config && yarn postgres migration:revert",
"postgres:migration:run": "yarn postgres migration:run"
},
"dependencies": {
Expand Down
4 changes: 3 additions & 1 deletion src/artemis/artemis.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ export class ArtemisService implements OnApplicationShutdown {
const model = new Model(context.message.body);
const validationErrors = await validate(model);
if (validationErrors.length) {
this.logger.error(`Validation errors: ${JSON.stringify(validationErrors)}`);
this.logger.error(
`Validation errors for "${listenOn}": ${JSON.stringify(validationErrors)}`
);
}

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

exports[`LocalOfflineTxRepo OfflineEvent test suite method: createTx should record the transaction request 1`] = `
{
"address": "someAddress",
"id": "1",
"nonce": 1,
"payload": {
"metadata": {
"memo": "test utils payload",
Expand All @@ -28,6 +30,7 @@ exports[`LocalOfflineTxRepo OfflineEvent test suite method: createTx should reco
"type": "bytes",
},
},
"status": "Requested",
"signature": "0x01",
"status": "Signed",
}
`;
6 changes: 6 additions & 0 deletions src/datastore/postgres/entities/offline-tx.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ export class OfflineTx extends BaseEntity {
@Column({ type: 'text', nullable: true })
signature: string;

@Column({ type: 'text' })
address: string;

@Column({ type: 'integer' })
nonce: number;

@Column({ type: 'json' })
payload: TransactionPayload;

Expand Down
23 changes: 23 additions & 0 deletions src/datastore/postgres/migrations/1705074621853-offline.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class Offline1705074621853 implements MigrationInterface {
name = 'Offline1705074621853';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE "offline_tx" ADD "address" text');
await queryRunner.query('UPDATE "offline_tx" SET "address" = \'\' WHERE "address" IS NULL');
await queryRunner.query('ALTER TABLE "offline_tx" ALTER COLUMN "address" SET NOT NULL');
await queryRunner.query('ALTER TABLE "offline_tx" ADD "nonce" integer');
await queryRunner.query('UPDATE "offline_tx" SET "nonce" = -1 WHERE "nonce" IS NULL');
await queryRunner.query('ALTER TABLE "offline_tx" ALTER COLUMN "nonce" SET NOT NULL');

await queryRunner.query('CREATE INDEX idx_address_nonce ON offline_tx (address, nonce)');
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX idx_address_nonce');

await queryRunner.query('ALTER TABLE "offline_tx" DROP COLUMN "nonce"');
await queryRunner.query('ALTER TABLE "offline_tx" DROP COLUMN "address"');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

exports[`PostgresOfflineTxRepo OfflineTxRepo test suite method: createTx should record the transaction request 1`] = `
OfflineTxModel {
"address": "someAddress",
"id": "someTestSuiteId",
"nonce": 1,
"payload": {
"metadata": {
"memo": "test utils payload",
Expand All @@ -28,6 +30,7 @@ OfflineTxModel {
"type": "bytes",
},
},
"status": "Requested",
"signature": "0x01",
"status": "Signed",
}
`;
5 changes: 2 additions & 3 deletions src/offline-signer/offline-signer.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ArtemisService } from '~/artemis/artemis.service';
import { AddressName } from '~/common/utils/amqp';
import { mockPolymeshLoggerProvider } from '~/logger/mock-polymesh-logger';
import { OfflineSignerService } from '~/offline-signer/offline-signer.service';
import { OfflineTxModel, OfflineTxStatus } from '~/offline-submitter/models/offline-tx.model';
import { OfflineRequestModel } from '~/offline-starter/models/offline-request.model';
import { SigningService } from '~/signing/services';
import { mockSigningProvider } from '~/signing/signing.mock';
import { mockArtemisServiceProvider } from '~/test-utils/service-mocks';
Expand Down Expand Up @@ -47,10 +47,9 @@ describe('OfflineSignerService', () => {

describe('method: autoSign', () => {
it('should sign and publish the signature', async () => {
const model = new OfflineTxModel({
const model = new OfflineRequestModel({
id: 'someId',
payload: {} as TransactionPayload,
status: OfflineTxStatus.Requested,
});

const mockSignature = '0x01';
Expand Down
6 changes: 3 additions & 3 deletions src/offline-signer/offline-signer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ArtemisService } from '~/artemis/artemis.service';
import { AddressName, QueueName } from '~/common/utils/amqp';
import { PolymeshLogger } from '~/logger/polymesh-logger.service';
import { OfflineSignatureModel } from '~/offline-signer/models/offline-signature.model';
import { OfflineTxModel } from '~/offline-submitter/models/offline-tx.model';
import { OfflineRequestModel } from '~/offline-starter/models/offline-request.model';
import { SigningService } from '~/signing/services';

/**
Expand All @@ -23,11 +23,11 @@ export class OfflineSignerService {
QueueName.Requests,
/* istanbul ignore next */
msg => this.autoSign(msg),
OfflineTxModel
OfflineRequestModel
);
}

public async autoSign(body: OfflineTxModel): Promise<void> {
public async autoSign(body: OfflineRequestModel): Promise<void> {
const { id: transactionId } = body;
this.logger.debug(`received request for signature: ${transactionId}`);

Expand Down
22 changes: 22 additions & 0 deletions src/offline-starter/models/offline-request.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* istanbul ignore file */

import { ApiProperty } from '@nestjs/swagger';
import { TransactionPayload } from '@polymeshassociation/polymesh-sdk/types';
import { IsString } from 'class-validator';

export class OfflineRequestModel {
@ApiProperty({
description: 'The internal ID',
})
@IsString()
id: string;

@ApiProperty({
description: 'The transaction payload to be signed',
})
payload: TransactionPayload;

constructor(model: OfflineRequestModel) {
Object.assign(this, model);
}
}
9 changes: 6 additions & 3 deletions src/offline-starter/offline-starter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ArtemisService } from '~/artemis/artemis.service';
import { AddressName } from '~/common/utils/amqp';
import { PolymeshLogger } from '~/logger/polymesh-logger.service';
import { OfflineReceiptModel } from '~/offline-starter/models/offline-receipt.model';
import { OfflineRequestModel } from '~/offline-starter/models/offline-request.model';

@Injectable()
export class OfflineStarterService {
Expand All @@ -25,13 +26,15 @@ export class OfflineStarterService {
const internalTxId = this.generateTxId();

const payload = await transaction.toSignablePayload({ ...metadata, internalTxId });
const topicName = AddressName.Requests;

this.logger.debug(`sending topic: ${topicName}`, topicName);
const delivery = await this.artemisService.sendMessage(topicName, {
const request = new OfflineRequestModel({
id: internalTxId,
payload,
});
const topicName = AddressName.Requests;

this.logger.debug(`sending topic: ${topicName}`, topicName);
const delivery = await this.artemisService.sendMessage(topicName, request);

const model = new OfflineReceiptModel({
deliveryId: new BigNumber(delivery.id),
Expand Down
19 changes: 15 additions & 4 deletions src/offline-submitter/models/offline-tx.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

import { ApiProperty } from '@nestjs/swagger';
import { TransactionPayload } from '@polymeshassociation/polymesh-sdk/types';
import { IsEnum, IsOptional, IsString } from 'class-validator';
import { IsEnum, IsNumber, IsOptional, IsString } from 'class-validator';

export enum OfflineTxStatus {
Requested = 'Requested',
Signed = 'Signed',
Finalized = 'Finalized',
}
Expand All @@ -27,14 +26,26 @@ export class OfflineTxModel {
})
@IsOptional()
@IsString()
signature?: string;
signature: string;

@ApiProperty({
description: 'The status of the transaction',
enum: OfflineTxStatus,
})
@IsEnum(OfflineTxStatus)
status: OfflineTxStatus = OfflineTxStatus.Requested;
status: OfflineTxStatus = OfflineTxStatus.Signed;

@ApiProperty({
description: 'The account signing the transaction',
})
@IsString()
readonly address: string;

@ApiProperty({
description: 'The nonce of the transaction',
})
@IsNumber()
readonly nonce: number;

@ApiProperty({
description: 'The block hash the transaction was included in',
Expand Down
5 changes: 4 additions & 1 deletion src/offline-submitter/offline-submitter.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ describe('OfflineSubmitterService', () => {
offlineModel = new OfflineTxModel({
id: 'someId',
payload: {} as TransactionPayload,
status: OfflineTxStatus.Requested,
status: OfflineTxStatus.Signed,
signature: '0x01',
nonce: 1,
address: 'someAddress',
});
});

Expand Down
5 changes: 5 additions & 0 deletions src/offline-submitter/offline-submitter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,17 @@ export class OfflineSubmitterService {
*/
public async submit(body: OfflineSignatureModel): Promise<void> {
const { id, signature, payload } = body;
const { address, nonce: rawNonce } = payload.payload;
const nonce = parseInt(rawNonce, 16);
this.logger.debug(`received signature for: ${id}`);

const transaction = await this.offlineTxRepo.createTx({
id,
payload,
status: OfflineTxStatus.Signed,
signature,
address,
nonce,
});

this.logger.log(`submitting transaction: ${id}`);
Expand All @@ -50,6 +54,7 @@ export class OfflineSubmitterService {
this.logger.log(`transaction finalized: ${id}`);

const msg = JSON.parse(JSON.stringify(result)); // make sure its serializes properly

await this.artemisService.sendMessage(AddressName.Finalizations, msg);

transaction.blockHash = result.blockHash as string;
Expand Down
3 changes: 1 addition & 2 deletions src/offline-submitter/repos/offline-tx.suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ export const testOfflineTxRepo = async (offlineTxRepo: OfflineTxRepo): Promise<v
describe('method: createTx', () => {
it('should record the transaction request', async () => {
const txParams = new OfflineTxModel({
...offlineTx,
id: 'someTestSuiteId',
payload: offlineTx.payload,
status: OfflineTxStatus.Requested,
});
model = await offlineTxRepo.createTx({ ...txParams });
expect(model).toMatchSnapshot();
Expand Down
5 changes: 4 additions & 1 deletion src/test-utils/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ const offlineTx = new OfflineTxModel({
rawPayload: { address: 'address', data: '0x01', type: 'bytes' },
metadata: { memo: 'test utils payload' },
},
status: OfflineTxStatus.Requested,
status: OfflineTxStatus.Signed,
signature: '0x01',
address: 'someAddress',
nonce: 1,
});

export const testAccount = createMock<Account>({ address: 'address' });
Expand Down

0 comments on commit aaf685b

Please sign in to comment.