Skip to content

Commit

Permalink
Online examples in docs - iteration 2 (#297)
Browse files Browse the repository at this point in the history
* feat: add docker commands to docs

* fix: add sendTransaction to the docs

* fix: add tx delegation

* fix: improve comments

* fix: update node version

* fix: revert node version

* fix: fix typo

* fix: improve examples
  • Loading branch information
fabiorigam authored Nov 28, 2023
1 parent a64f364 commit 9085373
Show file tree
Hide file tree
Showing 8 changed files with 330 additions and 146 deletions.
86 changes: 86 additions & 0 deletions docs/examples/thorest-client/delegated-transactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import {
Transaction,
TransactionUtils,
TransactionHandler,
dataUtils,
unitsUtils
} from '@vechainfoundation/vechain-sdk-core';
import {
HttpClient,
ThorestClient
} from '@vechainfoundation/vechain-sdk-network';
import { expect } from 'expect';

// Url of the solo network
const _soloUrl = 'http://localhost:8669';

// Solo network instance
const soloNetwork = new HttpClient(_soloUrl);

// Thorest client solo instance
const thorestSoloClient = new ThorestClient(soloNetwork);

// Get latest block
const latestBlock = await thorestSoloClient.blocks.getBestBlock();

// Create clauses
const clauses = [
{
to: '0x9e7911de289c3c856ce7f421034f66b6cde49c39',
value: unitsUtils.parseVET('10000').toString(), // VET transfer transaction
data: '0x'
}
];

// Get gas @NOTE this is an approximation
const gas = 5000 + TransactionUtils.intrinsicGas(clauses) * 5;

// Create delegated transaction
const delegatedTransaction = new Transaction({
chainTag: 0xf6,
blockRef: latestBlock !== null ? latestBlock.id.slice(0, 18) : '0x0',
expiration: 32,
clauses,
gasPriceCoef: 128,
gas,
dependsOn: null,
nonce: 12345678,
reserved: {
features: 1
}
});

// Private keys of sender
const pkSender =
'ea5383ac1f9e625220039a4afac6a7f868bf1ad4f48ce3a1dd78bd214ee4ace5';

/** Private key of delegate
* @NOTE The delegate account must have enough VET and VTHO to pay for the gas
*/
const pkDelegate =
'432f38bcf338c374523e83fdb2ebe1030aba63c7f1e81f7d76c5f53f4d42e766';

// Normal signature and delegation signature
const rawDelegatedSigned = TransactionHandler.signWithDelegator(
delegatedTransaction,
Buffer.from(pkSender, 'hex'),
Buffer.from(pkDelegate, 'hex')
).encoded;

// Send transaction
const send = await thorestSoloClient.transactions.sendTransaction(
`0x${rawDelegatedSigned.toString('hex')}`
);
expect(send).toBeDefined();
expect(send).toHaveProperty('id');
expect(dataUtils.isHexString(send.id)).toBe(true);

// Get transaction details and receipt
const transactionDetails = await thorestSoloClient.transactions.getTransaction(
send.id
);
const transactionReceipt =
await thorestSoloClient.transactions.getTransactionReceipt(send.id);

expect(transactionDetails).toBeDefined();
expect(transactionReceipt).toBeDefined();
127 changes: 60 additions & 67 deletions docs/examples/thorest-client/transactions.ts
Original file line number Diff line number Diff line change
@@ -1,80 +1,73 @@
import {
Transaction,
TransactionUtils,
TransactionHandler,
dataUtils,
unitsUtils
} from '@vechainfoundation/vechain-sdk-core';
import {
HttpClient,
ThorestClient
} from '@vechainfoundation/vechain-sdk-network';
import { expect } from 'expect';

// Url of the testnet network
const _testnetUrl = 'https://testnet.vechain.org/';
// Url of the solo network
const _soloUrl = 'http://localhost:8669';

// Testnet network instance
const testNetwork = new HttpClient(_testnetUrl);
// Solo network instance
const soloNetwork = new HttpClient(_soloUrl);

// Thorest client testnet instance
const thorestTestnetClient = new ThorestClient(testNetwork);
// Thorest client solo instance
const thorestSoloClient = new ThorestClient(soloNetwork);

// Retrieves the details of a transaction.
const transactionDetails =
await thorestTestnetClient.transactions.getTransaction(
'0x46d195f69e1ac3922d42c207e4705a3d1642883d97e58f7efc72f179ea326adb'
);
expect(transactionDetails).toEqual({
id: '0x46d195f69e1ac3922d42c207e4705a3d1642883d97e58f7efc72f179ea326adb',
chainTag: 39,
blockRef: '0x010284a0b704e751',
expiration: 2000,
clauses: [
{
to: '0x5d57f07dfeb8c224121433d5b1b401c82bd88f3d',
value: '0x2ea11e32ad50000',
data: '0x'
}
],
gasPriceCoef: 0,
gas: 41192,
origin: '0x2d4ed6b8abd00bc2ef0bdb2258a946c214d9d0af',
delegator: null,
nonce: '0x76eed751cef0e52d',
dependsOn: null,
size: 130,
meta: {
blockID:
'0x010284a1fea0635a2e47dd21f8a1761406df1013e5f4af79e311d8a27373980d',
blockNumber: 16942241,
blockTimestamp: 1699453780
// Get latest block
const latestBlock = await thorestSoloClient.blocks.getBestBlock();

// Create clauses
const clauses = [
{
to: '0x9e7911de289c3c856ce7f421034f66b6cde49c39',
value: unitsUtils.parseVET('10000').toString(), // VET transfer transaction
data: '0x'
}
];

// Create transaction
const transaction = new Transaction({
chainTag: 0xf6,
blockRef: latestBlock !== null ? latestBlock.id.slice(0, 18) : '0x0',
expiration: 32,
clauses,
gasPriceCoef: 128,
gas: 5000 + TransactionUtils.intrinsicGas(clauses) * 5,
dependsOn: null,
nonce: 12345678
});

// Retrieves the receipt of a transaction.
// Private keys of sender
const pkSender =
'ea5383ac1f9e625220039a4afac6a7f868bf1ad4f48ce3a1dd78bd214ee4ace5';

// Normal signature and delegation signature
const rawNormalSigned = TransactionHandler.sign(
transaction,
Buffer.from(pkSender, 'hex')
).encoded;

// Send transaction
const send = await thorestSoloClient.transactions.sendTransaction(
`0x${rawNormalSigned.toString('hex')}`
);
expect(send).toBeDefined();
expect(send).toHaveProperty('id');
expect(dataUtils.isHexString(send.id)).toBe(true);

// Get transaction details and receipt
const transactionDetails = await thorestSoloClient.transactions.getTransaction(
send.id
);
const transactionReceipt =
await thorestTestnetClient.transactions.getTransactionReceipt(
'0x46d195f69e1ac3922d42c207e4705a3d1642883d97e58f7efc72f179ea326adb'
);
expect(transactionReceipt).toEqual({
gasUsed: 21000,
gasPayer: '0x2d4ed6b8abd00bc2ef0bdb2258a946c214d9d0af',
paid: '0x2ea11e32ad50000',
reward: '0xdfd22a8cd98000',
reverted: false,
meta: {
blockID:
'0x010284a1fea0635a2e47dd21f8a1761406df1013e5f4af79e311d8a27373980d',
blockNumber: 16942241,
blockTimestamp: 1699453780,
txID: '0x46d195f69e1ac3922d42c207e4705a3d1642883d97e58f7efc72f179ea326adb',
txOrigin: '0x2d4ed6b8abd00bc2ef0bdb2258a946c214d9d0af'
},
outputs: [
{
contractAddress: null,
events: [],
transfers: [
{
sender: '0x2d4ed6b8abd00bc2ef0bdb2258a946c214d9d0af',
recipient: '0x5d57f07dfeb8c224121433d5b1b401c82bd88f3d',
amount: '0x2ea11e32ad50000'
}
]
}
]
});
await thorestSoloClient.transactions.getTransactionReceipt(send.id);

expect(transactionDetails).toBeDefined();
expect(transactionReceipt).toBeDefined();
6 changes: 3 additions & 3 deletions docs/examples/transactions/fee_delegation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ const body: TransactionBody = {

// Create private keys of sender and delegate
const pkSender = secp256k1.generatePrivateKey();
const nodeDelgate = HDNode.fromMnemonic(mnemonic.generate());
const pkDelegate = nodeDelgate.privateKey;
const nodeDelegate = HDNode.fromMnemonic(mnemonic.generate());
const pkDelegate = nodeDelegate.privateKey;
// Get address of delegate
const addrDelegate = nodeDelgate.address;
const addrDelegate = nodeDelegate.address;

// Sign transaction as sender and delegate
const unsignedTx = new Transaction(body);
Expand Down
4 changes: 3 additions & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"type": "module",
"version": "1.0.0",
"scripts": {
"test:examples": "ts-node-test examples/",
"test:before": "docker compose up -d",
"test:after": "docker compose down",
"test:examples": "yarn test:before && ts-node-test examples/ && yarn test:after",
"build": "find . -name \"*.md\" -type f -maxdepth 1 ! -name \"README.md\" -delete && tsup builddocs.ts && node dist/builddocs.cjs"
},
"dependencies": {
Expand Down
16 changes: 14 additions & 2 deletions docs/templates/thorest-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ The Thorest-client provides methods for developers to interact with transactions

[example](examples/thorest-client/transactions.ts)

In this example, the code initializes a Thorest client for the VechainThor testnet network and showcases two essential methods for interacting with transactions:
In this example, the code initializes a Thorest client for the VechainThor testnet network and showcases three essential methods for interacting with transactions:

- sendTransaction(raw: string): Promise<TransactionSendResult>

The `sendTransaction` method enables developers to broadcast a raw transaction to the VechainThor network. This method is crucial for initiating new transactions and executing smart contract functions.

- getTransaction(
id: string,
Expand All @@ -102,4 +106,12 @@ The `getTransaction` method facilitates the retrieval of detailed information ab
options?: GetTransactionReceiptInputOptions
): Promise<TransactionReceipt | null>

The `getTransactionReceipt` method allows developers to retrieve the receipt of a specific transaction on the VechainThor network. This includes information such as the transaction status, block number, and gas used.
The `getTransactionReceipt` method allows developers to retrieve the receipt of a specific transaction on the VechainThor network. This includes information such as the transaction status, block number, and gas used.

### Fee Delegation

Fee delegation is a feature on the VechainThor blockchain which enables the transaction sender to request another entity, a sponsor, to pay for the transaction fee on the sender's behalf. Fee delegation greatly improves the user experience, especially in the case of onboarding new users by removing the necessity of the user having to first acquire cryptocurrency assets before being able to interact on-chain.

The following code demonstrates how to use the Thorest-client with the fee delegation feature:

[example](examples/thorest-client/delegated-transactions.ts)
1 change: 0 additions & 1 deletion docs/templates/transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ Using the _BlockRef_ and _Expiration_ fields a transaction can be set to be proc

[example](examples/transactions/blockref_expiration.ts)


## Example: Transaction Dependency
A transaction can be set to only be processed after another transaction, therefore defining an execution order for transactions. The _DependsOn_ field is the Id of the transaction on which the current transaction depends on. If the transaction does not depend on others _DependsOn_ can be set to _null_

Expand Down
Loading

1 comment on commit 9085373

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test Coverage

Summary

Lines Statements Branches Functions
Coverage: 100%
100% (1094/1094) 100% (261/261) 100% (218/218)
Title Tests Skipped Failures Errors Time
core 319 0 💤 0 ❌ 0 🔥 1m 30s ⏱️
network 71 0 💤 0 ❌ 0 🔥 40.179s ⏱️
errors 30 0 💤 0 ❌ 0 🔥 12.272s ⏱️

Please sign in to comment.