Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add transaction builders #473

Merged
merged 4 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 21 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,81 +114,40 @@ Example of how to construct a transaction and push it to the network:

```ts
import {
Args,
CLValue,
CLValueOption,
CLValueUInt64,
CLValueUInt512,
Duration,
HttpHandler,
InitiatorAddr,
KeyAlgorithm,
PricingMode,
PrivateKey,
PublicKey,
RpcClient,
Timestamp,
TransactionEntryPoint,
TransactionScheduling,
TransactionTarget,
TransactionV1,
TransactionV1Payload,
TransactionEntryPointEnum,
PaymentLimitedMode
NativeTransferBuilder,
PrivateKey,
KeyAlgorithm,
PublicKey
} from 'casper-js-sdk';

const rpcHandler = new HttpHandler('http://<Node Address>:7777/rpc');
const rpcClient = new RpcClient(rpcHandler);

const privateKey = await PrivateKey.generate(KeyAlgorithm.ED25519);
const timestamp = new Timestamp(new Date());
const paymentAmount = '20000000000000';

const pricingMode = new PricingMode();
const paymentLimitedMode = new PaymentLimitedMode();
paymentLimitedMode.gasPriceTolerance = 1;
paymentLimitedMode.paymentAmount = paymentAmount;
paymentLimitedMode.standardPayment = true;
pricingMode.paymentLimited = paymentLimitedMode;

const args = Args.fromMap({
target: CLValue.newCLPublicKey(

const transaction = new NativeTransferBuilder()
.from(privateKey.publicKey)
.target(
PublicKey.fromHex(
'0202f5a92ab6da536e7b1a351406f3744224bec85d7acbab1497b65de48a1a707b64'
)
),
amount: CLValueUInt512.newCLUInt512(paymentAmount),
id: CLValueOption.newCLOption(CLValueUInt64.newCLUint64(3)) // memo ( optional )
});
)
.amount('25000000000') // Amount in motes
.id(Date.now())
.chainName('casper-net-1')
.payment(100_000_000)
.build();

const transactionTarget = new TransactionTarget({}); // Native target;
const entryPoint = new TransactionEntryPoint(
TransactionEntryPointEnum.Transfer
);
const scheduling = new TransactionScheduling({}); // Standard;

const transactionPayload = TransactionV1Payload.build({
initiatorAddr: new InitiatorAddr(privateKey.publicKey),
ttl: new Duration(1800000),
args,
timestamp,
entryPoint,
scheduling,
transactionTarget,
chainName: 'casper-net-1',
pricingMode
});

const transactionV1 = TransactionV1.makeTransactionV1(
transactionPayload
);
await transactionV1.sign(privateKey);
await transaction.sign(privateKey);

const tx = Transaction.fromTransactionV1(transactionV1);

const result = await rpcClient.putTransaction(tx);

console.log(`Transaction Hash: ${result.transactionHash}`);
try {
const result = await rpcClient.putTransaction(transaction);
console.log(`Transaction Hash: ${result.transactionHash}`);
} catch (e) {
console.error(e);
}
```

### Creating a legacy deploy
Expand Down
93 changes: 69 additions & 24 deletions migration-guide-v2-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,14 @@ const nativeTarget = new TransactionTarget({});
const stored = new StoredTarget();
const invocationTarget = new TransactionInvocationTarget();
invocationTarget.byHash = new Hash(Uint8Array.from([])); // an example of hash
storedTarget.runtime = 'VmCasperV1'; // an example of runtime
storedTarget.runtime = TransactionRuntime.vmCasperV1(); // an example of runtime
storedTarget.id = invocationTarget;

const storedTransactionTarget = new TransactionTarget(
undefined,
stored
);

// OR
const storedTransactionTarget1 = new TransactionTarget();
storedTransactionTarget1.stored = stored;
Expand All @@ -117,16 +118,15 @@ storedTransactionTarget1.stored = stored;
```typescript
const sessionTarget = new SessionTarget();
sessionTarget.moduleBytes = Uint8Array.from([]); // an example of module bytes
sessionTarget.runtime = 'VmCasperV1'; // an example of runtime
sessionTarget.transferredValue = 1000; // an example of transferredValue
sessionTarget.runtime = TransactionRuntime.vmCasperV1(); // an example of runtime
sessionTarget.isInstallUpgrade = true; // an example of isInstallUpgrade
sessionTarget.seed = new Hash(Uint8Array.from([])); // an example of seed

const sessionTransactionTarget = new TransactionTarget(
undefined,
undefined,
sessionTarget
);

// OR
const sessionTransactionTarget1 = new TransactionTarget();
sessionTransactionTarget1.session = sessionTarget;
Expand Down Expand Up @@ -158,19 +158,20 @@ Specifies how transaction fees are calculated. Supports three modes:

#### Examples:

- **FixedMode**:
- **PaymentLimitedMode**:

```typescript
const fixedMode = new FixedMode();
fixedMode.gasPriceTolerance = 2;
fixedMode.additionalComputationFactor = 1;
const paymentLimited = new PaymentLimitedMode();
paymentLimited.standardPayment = true;
paymentLimited.paymentAmount = '250000000';
paymentLimited.gasPriceTolerance = 1;
```

- **Assign Pricing Mode**:

```typescript
const pricingMode = new PricingMode();
pricingMode.fixed = fixedMode;
pricingMode.paymentLimited = paymentLimited;
```

---
Expand All @@ -197,10 +198,10 @@ const publicKey = privateKey.publicKey;

```typescript
const args = Args.fromMap({
target: CLValue.newCLPublicKey(
PublicKey.fromHex('<Recipient Public Key>')
),
amount: CLValueUInt512.newCLUInt512('2000000000') // 2 CSPR
target: CLValue.newCLPublicKey(
PublicKey.fromHex('<Recipient Public Key>')
),
amount: CLValueUInt512.newCLUInt512('2000000000') // 2 CSPR
});
```

Expand All @@ -216,7 +217,7 @@ const transactionTarget = new TransactionTarget({}); // Native target;

```typescript
const entryPoint = new TransactionEntryPoint(
TransactionEntryPointEnum.Transfer
TransactionEntryPointEnum.Transfer
);
```

Expand All @@ -242,19 +243,19 @@ pricingMode.paymentLimited = paymentLimitedMode;

```typescript
const transactionPayload = TransactionV1Payload.build({
initiatorAddr: new InitiatorAddr(publicKey),
ttl: new Duration(1800000),
args,
timestamp: new Timestamp(new Date()),
entryPoint,
scheduling,
transactionTarget,
chainName: 'casper-net-1',
pricingMode
initiatorAddr: new InitiatorAddr(publicKey),
ttl: new Duration(1800000),
args,
timestamp: new Timestamp(new Date()),
entryPoint,
scheduling,
transactionTarget,
chainName: 'casper-net-1',
pricingMode
});

const transaction = TransactionV1.makeTransactionV1(
transactionPayload
transactionPayload
);
await transaction.sign(privateKey);
```
Expand All @@ -265,3 +266,47 @@ await transaction.sign(privateKey);
const result = await rpcClient.putTransactionV1(transaction);
console.log(`Transaction Hash: ${result.transactionHash}`);
```

## Using [TransactionBuilder](./src/types/TransactionBuilder.md)

The `TransactionBuilder` is a base class used to create various types of transactions. By extending this class, you can build custom transaction types with specific methods and properties.

#### Example of how to construct a transaction with TransactionBuilder and push it to the network:

```ts
import {
HttpHandler,
RpcClient,
NativeTransferBuilder,
PrivateKey,
KeyAlgorithm,
PublicKey
} from 'casper-js-sdk';

const rpcHandler = new HttpHandler('http://<Node Address>:7777/rpc');
const rpcClient = new RpcClient(rpcHandler);

const privateKey = await PrivateKey.generate(KeyAlgorithm.ED25519);

const transaction = new NativeTransferBuilder()
.from(sender.publicKey)
.target(
PublicKey.fromHex(
'0202f5a92ab6da536e7b1a351406f3744224bec85d7acbab1497b65de48a1a707b64'
)
)
.amount('25000000000') // Amount in motes
.id(Date.now())
.chainName('casper-net-1')
.payment(100_000_000)
.build();

await transaction.sign(privateKey);

try {
const result = await rpcClient.putTransaction(transaction);
console.log(`Transaction Hash: ${result.transactionHash}`);
} catch (e) {
console.error(e);
}
```
4 changes: 3 additions & 1 deletion src/types/Deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,9 @@ export class Deploy {
* @param keys The private key used to sign the deploy.
*/
public async sign(keys: PrivateKey): Promise<void> {
const signatureBytes = await keys.sign(this.hash.toBytes());
const signatureBytes = await keys.signAndAddAlgorithmBytes(
this.hash.toBytes()
);
const signature = new HexBytes(signatureBytes);
this.approvals.push(new Approval(keys.publicKey, signature));
}
Expand Down
29 changes: 29 additions & 0 deletions src/types/Transaction.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
CLValueUInt64
} from './clvalue';
import { TransactionV1Payload } from './TransactionV1Payload';
import { NativeTransferBuilder } from './TransactionBuilder';

describe('Test Transaction', () => {
it('should create a TransactionV1 with correct payload instance', async () => {
Expand Down Expand Up @@ -90,4 +91,32 @@ describe('Test Transaction', () => {
expect(transaction.payload.fields.scheduling).to.deep.equal(scheduling);
expect(transaction.payload.fields.entryPoint).to.deep.equal(entryPoint);
});

it('should create native transfer TransactionV1 with builder', async () => {
const sender = await PrivateKey.generate(KeyAlgorithm.ED25519);

const transaction = new NativeTransferBuilder()
.from(sender.publicKey)
.target(
PublicKey.fromHex(
'0202f5a92ab6da536e7b1a351406f3744224bec85d7acbab1497b65de48a1a707b64'
)
)
.amount('25000000000')
.id(Date.now())
.chainName('casper-net-1')
.payment(100_000_000)
.build();

await transaction.sign(sender);

const transactionV1 = transaction.getTransactionV1()!;
const transactionPaymentAmount = transactionV1.payload.fields.args.args
.get('amount')!
.toString();

assert.deepEqual(transaction.approvals[0].signer, sender.publicKey);
assert.deepEqual(parseInt(transactionPaymentAmount, 10), 25000000000);
expect(transactionV1.payload.chainName).to.deep.equal('casper-net-1');
});
});
13 changes: 10 additions & 3 deletions src/types/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ export class TransactionV1 {
* @param keys The private key to sign the transaction.
*/
async sign(keys: PrivateKey): Promise<void> {
const signatureBytes = await keys.sign(this.hash.toBytes());
const signatureBytes = await keys.signAndAddAlgorithmBytes(
this.hash.toBytes()
);
const signature = new HexBytes(signatureBytes);

if (!this.approvals) {
Expand Down Expand Up @@ -467,7 +469,10 @@ export class Transaction {
}

public getTransactionWrapper(): TransactionWrapper {
return new TransactionWrapper(this.originDeployV1, this.originTransactionV1);
return new TransactionWrapper(
this.originDeployV1,
this.originTransactionV1
);
}

/**
Expand All @@ -489,7 +494,9 @@ export class Transaction {
* @param key The private key to sign the transaction.
*/
async sign(key: PrivateKey): Promise<void> {
const signatureBytes = await key.sign(this.hash.toBytes());
const signatureBytes = await key.signAndAddAlgorithmBytes(
this.hash.toBytes()
);
this.setSignature(signatureBytes, key.publicKey);
}

Expand Down
Loading
Loading