diff --git a/src/delegation/delegationController.ts b/src/delegation/delegationController.ts index 413968e5..e8ad9c78 100644 --- a/src/delegation/delegationController.ts +++ b/src/delegation/delegationController.ts @@ -7,7 +7,7 @@ import { TransactionsFactoryConfig } from "../transactionsFactories"; import { TransactionWatcher } from "../transactionWatcher"; import { DelegationTransactionsFactory } from "./delegationTransactionsFactory"; import { DelegationTransactionsOutcomeParser } from "./delegationTransactionsOutcomeParser"; -import * as inputs from "./resources"; +import * as resources from "./resources"; export class DelegationController { private transactionAwaiter: TransactionWatcher; @@ -27,7 +27,7 @@ export class DelegationController { async createTransactionForNewDelegationContract( sender: IAccount, nonce: bigint, - options: inputs.NewDelegationContractInput, + options: resources.NewDelegationContractInput, ): Promise { const transaction = this.factory.createTransactionForNewDelegationContract(sender.address, options); @@ -49,7 +49,7 @@ export class DelegationController { async createTransactionForAddingNodes( sender: IAccount, nonce: bigint, - options: inputs.AddNodesInput, + options: resources.AddNodesInput, ): Promise { const transaction = this.factory.createTransactionForAddingNodes(sender.address, options); @@ -62,7 +62,7 @@ export class DelegationController { async createTransactionForRemovingNodes( sender: IAccount, nonce: bigint, - options: inputs.ManageNodesInput, + options: resources.ManageNodesInput, ): Promise { const transaction = this.factory.createTransactionForRemovingNodes(sender.address, options); @@ -75,7 +75,7 @@ export class DelegationController { async createTransactionForStakingNodes( sender: IAccount, nonce: bigint, - options: inputs.ManageNodesInput, + options: resources.ManageNodesInput, ): Promise { const transaction = this.factory.createTransactionForStakingNodes(sender.address, options); @@ -88,7 +88,7 @@ export class DelegationController { async createTransactionForUnbondingNodes( sender: IAccount, nonce: bigint, - options: inputs.ManageNodesInput, + options: resources.ManageNodesInput, ): Promise { const transaction = this.factory.createTransactionForUnbondingNodes(sender.address, options); @@ -101,7 +101,7 @@ export class DelegationController { async createTransactionForUnstakingNodes( sender: IAccount, nonce: bigint, - options: inputs.ManageNodesInput, + options: resources.ManageNodesInput, ): Promise { const transaction = this.factory.createTransactionForUnstakingNodes(sender.address, options); @@ -114,7 +114,7 @@ export class DelegationController { async createTransactionForUnjailingNodes( sender: IAccount, nonce: bigint, - options: inputs.UnjailingNodesInput, + options: resources.UnjailingNodesInput, ): Promise { const transaction = this.factory.createTransactionForUnjailingNodes(sender.address, options); @@ -127,7 +127,7 @@ export class DelegationController { async createTransactionForChangingServiceFee( sender: IAccount, nonce: bigint, - options: inputs.ChangeServiceFee, + options: resources.ChangeServiceFee, ): Promise { const transaction = this.factory.createTransactionForChangingServiceFee(sender.address, options); @@ -140,7 +140,7 @@ export class DelegationController { async createTransactionForModifyingDelegationCap( sender: IAccount, nonce: bigint, - options: inputs.ModifyDelegationCapInput, + options: resources.ModifyDelegationCapInput, ): Promise { const transaction = this.factory.createTransactionForModifyingDelegationCap(sender.address, options); @@ -153,7 +153,7 @@ export class DelegationController { async createTransactionForSettingAutomaticActivation( sender: IAccount, nonce: bigint, - options: inputs.ManageDelegationContractInput, + options: resources.ManageDelegationContractInput, ): Promise { const transaction = this.factory.createTransactionForSettingAutomaticActivation(sender.address, options); @@ -166,7 +166,7 @@ export class DelegationController { async createTransactionForUnsettingAutomaticActivation( sender: IAccount, nonce: bigint, - options: inputs.ManageDelegationContractInput, + options: resources.ManageDelegationContractInput, ): Promise { const transaction = this.factory.createTransactionForUnsettingAutomaticActivation(sender.address, options); @@ -179,7 +179,7 @@ export class DelegationController { async createTransactionForSettingCapCheckOnRedelegateRewards( sender: IAccount, nonce: bigint, - options: inputs.ManageDelegationContractInput, + options: resources.ManageDelegationContractInput, ): Promise { const transaction = this.factory.createTransactionForSettingCapCheckOnRedelegateRewards( sender.address, @@ -195,7 +195,7 @@ export class DelegationController { async createTransactionForUnsettingCapCheckOnRedelegateRewards( sender: IAccount, nonce: bigint, - options: inputs.ManageDelegationContractInput, + options: resources.ManageDelegationContractInput, ): Promise { const transaction = this.factory.createTransactionForUnsettingCapCheckOnRedelegateRewards( sender.address, @@ -211,7 +211,7 @@ export class DelegationController { async createTransactionForSettingMetadata( sender: IAccount, nonce: bigint, - options: inputs.SetContractMetadataInput, + options: resources.SetContractMetadataInput, ): Promise { const transaction = this.factory.createTransactionForSettingMetadata(sender.address, options); @@ -224,7 +224,7 @@ export class DelegationController { async createTransactionForDelegating( sender: IAccount, nonce: bigint, - options: inputs.DelegateActionsInput, + options: resources.DelegateActionsInput, ): Promise { const transaction = this.factory.createTransactionForDelegating(sender.address, options); @@ -237,7 +237,7 @@ export class DelegationController { async createTransactionForClaimingRewards( sender: IAccount, nonce: bigint, - options: inputs.ManageDelegationContractInput, + options: resources.ManageDelegationContractInput, ): Promise { const transaction = this.factory.createTransactionForClaimingRewards(sender.address, options); @@ -250,7 +250,7 @@ export class DelegationController { async createTransactionForRedelegatingRewards( sender: IAccount, nonce: bigint, - options: inputs.ManageDelegationContractInput, + options: resources.ManageDelegationContractInput, ): Promise { const transaction = this.factory.createTransactionForRedelegatingRewards(sender.address, options); @@ -263,7 +263,7 @@ export class DelegationController { async createTransactionForUndelegating( sender: IAccount, nonce: bigint, - options: inputs.DelegateActionsInput, + options: resources.DelegateActionsInput, ): Promise { const transaction = this.factory.createTransactionForUndelegating(sender.address, options); @@ -276,7 +276,7 @@ export class DelegationController { async createTransactionForWithdrawing( sender: IAccount, nonce: bigint, - options: inputs.ManageDelegationContractInput, + options: resources.ManageDelegationContractInput, ): Promise { const transaction = this.factory.createTransactionForWithdrawing(sender.address, options); diff --git a/src/index.ts b/src/index.ts index f45b9047..87ed40c9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,6 +23,7 @@ export * from "./logger"; export * from "./message"; export * from "./networkParams"; export * from "./networkProviders"; +export * from "./relayed"; export * from "./relayedTransactionV1Builder"; export * from "./relayedTransactionV2Builder"; export * from "./signableMessage"; diff --git a/src/relayed/index.ts b/src/relayed/index.ts new file mode 100644 index 00000000..fbf0c51f --- /dev/null +++ b/src/relayed/index.ts @@ -0,0 +1,2 @@ +export * from "./relayedController"; +export * from "./relayedTransactionsFactory"; diff --git a/src/relayed/relayedController.ts b/src/relayed/relayedController.ts new file mode 100644 index 00000000..2b48500e --- /dev/null +++ b/src/relayed/relayedController.ts @@ -0,0 +1,49 @@ +import { IAccount } from "../accounts/interfaces"; +import { Transaction } from "../transaction"; +import { TransactionComputer } from "../transactionComputer"; +import { TransactionsFactoryConfig } from "../transactionsFactories"; +import { RelayedTransactionsFactory } from "./relayedTransactionsFactory"; +import { RelayedV1TransactionInput, RelayedV2TransactionInput } from "./resources"; + +export class RelayedController { + private factory: RelayedTransactionsFactory; + private txComputer: TransactionComputer; + + /** + * The transactions are created from the perspective of the relayer. + * The 'sender' represents the relayer. + */ + constructor(options: { chainID: string }) { + this.factory = new RelayedTransactionsFactory({ + config: new TransactionsFactoryConfig(options), + }); + this.txComputer = new TransactionComputer(); + } + + async createRelayedV1Transaction( + sender: IAccount, + nonce: bigint, + options: RelayedV1TransactionInput, + ): Promise { + const transaction = this.factory.createRelayedV1Transaction(sender.address, options); + + transaction.nonce = nonce; + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } + + async createRelayedV2Transaction( + sender: IAccount, + nonce: bigint, + options: RelayedV2TransactionInput, + ): Promise { + const transaction = this.factory.createRelayedV2Transaction(sender.address, options); + + transaction.nonce = nonce; + transaction.gasLimit = BigInt(0); + transaction.signature = await sender.sign(this.txComputer.computeBytesForSigning(transaction)); + + return transaction; + } +} diff --git a/src/transactionsFactories/relayedTransactionsFactory.spec.ts b/src/relayed/relayedTransactionsFactory.spec.ts similarity index 95% rename from src/transactionsFactories/relayedTransactionsFactory.spec.ts rename to src/relayed/relayedTransactionsFactory.spec.ts index 6c61d331..cbd41f33 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.spec.ts +++ b/src/relayed/relayedTransactionsFactory.spec.ts @@ -2,8 +2,8 @@ import { assert } from "chai"; import { TestWallet, loadTestWallets } from "../testutils"; import { Transaction } from "../transaction"; import { TransactionComputer } from "../transactionComputer"; +import { TransactionsFactoryConfig } from "../transactionsFactories/transactionsFactoryConfig"; import { RelayedTransactionsFactory } from "./relayedTransactionsFactory"; -import { TransactionsFactoryConfig } from "./transactionsFactoryConfig"; describe("test relayed transactions factory", function () { const config = new TransactionsFactoryConfig({ chainID: "T" }); @@ -25,7 +25,7 @@ describe("test relayed transactions factory", function () { }); assert.throws(() => { - factory.createRelayedV1Transaction({ innerTransaction: innerTransaction, relayerAddress: bob.address }), + factory.createRelayedV1Transaction(bob.address, { innerTransaction: innerTransaction }), "The inner transaction is not signed"; }); @@ -33,7 +33,7 @@ describe("test relayed transactions factory", function () { innerTransaction.signature = Buffer.from("invalidsignature"); assert.throws(() => { - factory.createRelayedV1Transaction({ innerTransaction: innerTransaction, relayerAddress: bob.address }), + factory.createRelayedV1Transaction(bob.address, { innerTransaction: innerTransaction }), "The gas limit is not set for the inner transaction"; }); }); @@ -51,9 +51,8 @@ describe("test relayed transactions factory", function () { const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); innerTransaction.signature = await bob.signer.sign(serializedInnerTransaction); - const relayedTransaction = factory.createRelayedV1Transaction({ + const relayedTransaction = factory.createRelayedV1Transaction(alice.getAddress(), { innerTransaction: innerTransaction, - relayerAddress: alice.address, }); relayedTransaction.nonce = 2627n; @@ -85,9 +84,8 @@ describe("test relayed transactions factory", function () { const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); innerTransaction.signature = await carol.signer.sign(serializedInnerTransaction); - const relayedTransaction = factory.createRelayedV1Transaction({ + const relayedTransaction = factory.createRelayedV1Transaction(frank.getAddress(), { innerTransaction: innerTransaction, - relayerAddress: frank.address, }); relayedTransaction.nonce = 715n; @@ -119,9 +117,8 @@ describe("test relayed transactions factory", function () { const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); innerTransaction.signature = await carol.signer.sign(serializedInnerTransaction); - const relayedTransaction = factory.createRelayedV1Transaction({ + const relayedTransaction = factory.createRelayedV1Transaction(frank.getAddress(), { innerTransaction: innerTransaction, - relayerAddress: frank.address, }); relayedTransaction.nonce = 715n; @@ -155,9 +152,8 @@ describe("test relayed transactions factory", function () { innerTransaction.signature = await bob.signer.sign(serializedInnerTransaction); innerTransaction.guardianSignature = await grace.signer.sign(serializedInnerTransaction); - const relayedTransaction = factory.createRelayedV1Transaction({ + const relayedTransaction = factory.createRelayedV1Transaction(alice.getAddress(), { innerTransaction: innerTransaction, - relayerAddress: alice.address, }); relayedTransaction.nonce = 2627n; @@ -191,9 +187,8 @@ describe("test relayed transactions factory", function () { innerTransaction.signature = await bob.signer.sign(serializedInnerTransaction); innerTransaction.guardianSignature = await grace.signer.sign(serializedInnerTransaction); - const relayedTransaction = factory.createRelayedV1Transaction({ + const relayedTransaction = factory.createRelayedV1Transaction(alice.getAddress(), { innerTransaction: innerTransaction, - relayerAddress: alice.address, }); relayedTransaction.nonce = 2627n; relayedTransaction.options = 2; @@ -222,10 +217,9 @@ describe("test relayed transactions factory", function () { }); assert.throws(() => { - factory.createRelayedV2Transaction({ + factory.createRelayedV2Transaction(carol.getAddress(), { innerTransaction: innerTransaction, innerTransactionGasLimit: 50000n, - relayerAddress: carol.address, }), "The gas limit should not be set for the inner transaction"; }); @@ -233,10 +227,9 @@ describe("test relayed transactions factory", function () { innerTransaction.gasLimit = 0n; assert.throws(() => { - factory.createRelayedV2Transaction({ + factory.createRelayedV2Transaction(carol.getAddress(), { innerTransaction: innerTransaction, innerTransactionGasLimit: 50000n, - relayerAddress: carol.address, }), "The inner transaction is not signed"; }); @@ -257,10 +250,9 @@ describe("test relayed transactions factory", function () { const serializedInnerTransaction = transactionComputer.computeBytesForSigning(innerTransaction); innerTransaction.signature = await bob.signer.sign(serializedInnerTransaction); - const relayedTransaction = factory.createRelayedV2Transaction({ + const relayedTransaction = factory.createRelayedV2Transaction(alice.getAddress(), { innerTransaction: innerTransaction, innerTransactionGasLimit: 60000000n, - relayerAddress: alice.address, }); relayedTransaction.nonce = 37n; diff --git a/src/transactionsFactories/relayedTransactionsFactory.ts b/src/relayed/relayedTransactionsFactory.ts similarity index 90% rename from src/transactionsFactories/relayedTransactionsFactory.ts rename to src/relayed/relayedTransactionsFactory.ts index 13c2a8e6..52f00853 100644 --- a/src/transactionsFactories/relayedTransactionsFactory.ts +++ b/src/relayed/relayedTransactionsFactory.ts @@ -2,7 +2,7 @@ import BigNumber from "bignumber.js"; import { AddressValue, ArgSerializer, BytesValue, U64Value } from "../abi"; import { Address } from "../address"; import { ErrInvalidInnerTransaction } from "../errors"; -import { IAddress, ITransaction } from "../interface"; +import { ITransaction } from "../interface"; import { Transaction } from "../transaction"; const JSONbig = require("json-bigint"); @@ -23,7 +23,7 @@ export class RelayedTransactionsFactory { this.config = options.config; } - createRelayedV1Transaction(options: { innerTransaction: ITransaction; relayerAddress: IAddress }): Transaction { + createRelayedV1Transaction(relayerAddress: Address, options: { innerTransaction: ITransaction }): Transaction { if (!options.innerTransaction.gasLimit) { throw new ErrInvalidInnerTransaction("The gas limit is not set for the inner transaction"); } @@ -40,18 +40,20 @@ export class RelayedTransactionsFactory { return new Transaction({ chainID: this.config.chainID, - sender: options.relayerAddress.bech32(), + sender: relayerAddress.bech32(), receiver: options.innerTransaction.sender, gasLimit: gasLimit, data: Buffer.from(data), }); } - createRelayedV2Transaction(options: { - innerTransaction: ITransaction; - innerTransactionGasLimit: bigint; - relayerAddress: IAddress; - }): Transaction { + createRelayedV2Transaction( + relayerAddress: Address, + options: { + innerTransaction: ITransaction; + innerTransactionGasLimit: bigint; + }, + ): Transaction { if (options.innerTransaction.gasLimit) { throw new ErrInvalidInnerTransaction("The gas limit should not be set for the inner transaction"); } @@ -73,7 +75,7 @@ export class RelayedTransactionsFactory { const gasLimit = options.innerTransactionGasLimit + this.config.minGasLimit + additionalGasForDataLength; return new Transaction({ - sender: options.relayerAddress.bech32(), + sender: relayerAddress.bech32(), receiver: options.innerTransaction.sender, value: 0n, gasLimit: gasLimit, diff --git a/src/relayed/resources.ts b/src/relayed/resources.ts new file mode 100644 index 00000000..cb049465 --- /dev/null +++ b/src/relayed/resources.ts @@ -0,0 +1,7 @@ +import { ITransaction } from "../interface"; + +export type RelayedV1TransactionInput = { innerTransaction: ITransaction }; +export type RelayedV2TransactionInput = { + innerTransaction: ITransaction; + innerTransactionGasLimit: bigint; +}; diff --git a/src/transactionsFactories/index.ts b/src/transactionsFactories/index.ts index e3edd8fc..39ea35ba 100644 --- a/src/transactionsFactories/index.ts +++ b/src/transactionsFactories/index.ts @@ -1,5 +1,3 @@ -export * from "../accountManagement/accountTransactionsFactory"; -export * from "./relayedTransactionsFactory"; export * from "./smartContractTransactionsFactory"; export * from "./tokenManagementTransactionsFactory"; export * from "./transactionsFactoryConfig";