-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'merge-main-in-feat-erdjs-v12' into guardedTransaction
- Loading branch information
Showing
8 changed files
with
598 additions
and
312 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { loadTestWallets, TestWallet } from "./testutils"; | ||
import { assert} from "chai"; | ||
import * as errors from "./errors"; | ||
import { RelayedTransactionV1Builder } from "./relayedTransactionV1Builder"; | ||
import { Transaction } from "./transaction"; | ||
import { Address } from "./address"; | ||
import { TransactionPayload } from "./transactionPayload"; | ||
|
||
describe("test relayed v1 transaction builder", function () { | ||
let alice: TestWallet, bob: TestWallet; | ||
|
||
before(async function () { | ||
({alice, bob} = await loadTestWallets()); | ||
}); | ||
|
||
it("should throw exception if args were not set", async function () { | ||
const builder = new RelayedTransactionV1Builder(); | ||
assert.throw(() => builder.build(), errors.ErrInvalidRelayedV1BuilderArguments); | ||
|
||
const innerTx = new Transaction({ | ||
nonce: 15, | ||
sender: alice.address, | ||
receiver: Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"), | ||
gasLimit: 10000000, | ||
chainID: "1", | ||
data: new TransactionPayload("getContractConfig"), | ||
}); | ||
builder.setInnerTransaction(innerTx); | ||
assert.throw(() => builder.build(), errors.ErrInvalidRelayedV1BuilderArguments); | ||
|
||
const networkConfig = { | ||
MinGasLimit: 50_000, | ||
GasPerDataByte: 1_500, | ||
GasPriceModifier: 0.01, | ||
ChainID: "T" | ||
}; | ||
builder.setNetworkConfig(networkConfig); | ||
assert.throw(() => builder.build(), errors.ErrInvalidRelayedV1BuilderArguments); | ||
|
||
builder.setRelayerAddress(alice.getAddress()); | ||
assert.doesNotThrow(() => builder.build()); | ||
}); | ||
|
||
it("should compute relayed v1 transaction", async function () { | ||
const networkConfig = { | ||
MinGasLimit: 50_000, | ||
GasPerDataByte: 1_500, | ||
GasPriceModifier: 0.01, | ||
ChainID: "T" | ||
}; | ||
|
||
const innerTx = new Transaction({ | ||
nonce: 198, | ||
sender: bob.address, | ||
receiver: Address.fromBech32("erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"), | ||
gasLimit: 60000000, | ||
chainID: networkConfig.ChainID, | ||
data: new TransactionPayload("getContractConfig"), | ||
}); | ||
|
||
await bob.signer.sign(innerTx); | ||
|
||
const builder = new RelayedTransactionV1Builder(); | ||
const relayedTxV1 = builder | ||
.setInnerTransaction(innerTx) | ||
.setRelayerNonce(2627) | ||
.setNetworkConfig(networkConfig) | ||
.setRelayerAddress(alice.address) | ||
.build(); | ||
|
||
await alice.signer.sign(relayedTxV1); | ||
|
||
assert.equal(relayedTxV1.getNonce().valueOf(), 2627); | ||
assert.equal(relayedTxV1.getData().toString(), "relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414141415141414141414141414141414141414141414141414141414141432f2f383d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225a3256305132397564484a68593352446232356d6157633d222c227369676e6174757265223a2239682b6e6742584f5536776674315464437368534d4b3454446a5a32794f74686336564c576e3478724d5a706248427738677a6c6659596d362b766b505258303764634a562b4745635462616a7049692b5a5a5942773d3d222c22636861696e4944223a2256413d3d222c2276657273696f6e223a317d"); | ||
assert.equal(relayedTxV1.getSignature().hex(), "c7d2c3b971f44eca676c10624d3c4319f8898af159f003e1e59f446cb75e5a294c9f0758d800e04d3daff11e67d20c4c1f85fd54aad6deb947ef391e6dd09d07"); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { Transaction } from "./transaction"; | ||
import { IAddress, INonce } from "./interface"; | ||
import { INetworkConfig } from "./interfaceOfNetwork"; | ||
import { ErrInvalidRelayedV1BuilderArguments } from "./errors"; | ||
import { TransactionPayload } from "./transactionPayload"; | ||
import { ContractFunction, StringValue } from "./smartcontracts"; | ||
import { Address } from "./address"; | ||
import BigNumber from "bignumber.js"; | ||
|
||
export class RelayedTransactionV1Builder { | ||
innerTransaction: Transaction | undefined; | ||
relayerAddress: IAddress | undefined; | ||
relayerNonce: INonce | undefined; | ||
netConfig: INetworkConfig | undefined; | ||
|
||
/** | ||
* Sets the inner transaction to be used. It has to be already signed. | ||
* | ||
* @param {Transaction} transaction The inner transaction to be used | ||
*/ | ||
setInnerTransaction(transaction: Transaction): RelayedTransactionV1Builder { | ||
this.innerTransaction = transaction; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the network config to be used for building the relayed v1 transaction | ||
* | ||
* @param {INetworkConfig} netConfig The network configuration to be used | ||
*/ | ||
setNetworkConfig(netConfig: INetworkConfig): RelayedTransactionV1Builder { | ||
this.netConfig = netConfig; | ||
return this; | ||
} | ||
|
||
/** | ||
* Sets the address of the relayer (the one that will actually pay the fee) | ||
* | ||
* @param relayerAddress | ||
*/ | ||
setRelayerAddress(relayerAddress: IAddress): RelayedTransactionV1Builder { | ||
this.relayerAddress = relayerAddress; | ||
return this; | ||
} | ||
|
||
/** | ||
* (optional) Sets the nonce of the relayer | ||
* | ||
* @param relayerNonce | ||
*/ | ||
setRelayerNonce(relayerNonce: INonce) : RelayedTransactionV1Builder { | ||
this.relayerNonce = relayerNonce; | ||
return this; | ||
} | ||
|
||
/** | ||
* Tries to build the relayed v1 transaction based on the previously set fields | ||
* | ||
* @throws ErrInvalidRelayedV1BuilderArguments | ||
* @return Transaction | ||
*/ | ||
build(): Transaction { | ||
if (!this.innerTransaction || !this.netConfig || !this.relayerAddress || !this.innerTransaction.getSignature()) { | ||
throw new ErrInvalidRelayedV1BuilderArguments(); | ||
} | ||
|
||
const serializedTransaction = this.prepareInnerTransaction(); | ||
const payload = TransactionPayload.contractCall() | ||
.setFunction(new ContractFunction("relayedTx")) | ||
.setArgs([ | ||
new StringValue(serializedTransaction), | ||
]) | ||
.build(); | ||
|
||
const gasLimit = this.netConfig.MinGasLimit + this.netConfig.GasPerDataByte * payload.length() + this.innerTransaction.getGasLimit().valueOf(); | ||
let relayedTransaction = new Transaction({ | ||
nonce: this.relayerNonce, | ||
sender: this.relayerAddress, | ||
receiver: this.innerTransaction.getSender(), | ||
value: 0, | ||
gasLimit: gasLimit, | ||
data: payload, | ||
chainID: this.netConfig.ChainID, | ||
}); | ||
|
||
if (this.relayerNonce) { | ||
relayedTransaction.setNonce(this.relayerNonce); | ||
} | ||
|
||
return relayedTransaction; | ||
} | ||
|
||
private prepareInnerTransaction(): string { | ||
if (!this.innerTransaction) { | ||
return ""; | ||
} | ||
|
||
const txObject = { | ||
"nonce": this.innerTransaction.getNonce().valueOf(), | ||
"sender": new Address(this.innerTransaction.getSender().bech32()).pubkey().toString("base64"), | ||
"receiver": new Address(this.innerTransaction.getReceiver().bech32()).pubkey().toString("base64"), | ||
"value": new BigNumber(this.innerTransaction.getValue().toString(), 10).toNumber(), | ||
"gasPrice": this.innerTransaction.getGasPrice().valueOf(), | ||
"gasLimit": this.innerTransaction.getGasLimit().valueOf(), | ||
"data": this.innerTransaction.getData().valueOf().toString("base64"), | ||
"signature": Buffer.from(this.innerTransaction.getSignature().hex(), 'hex').toString("base64"), | ||
"chainID": Buffer.from(this.innerTransaction.getChainID().valueOf()).toString("base64"), | ||
"version": this.innerTransaction.getVersion().valueOf(), | ||
}; | ||
|
||
return JSON.stringify(txObject); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters