Skip to content

Commit

Permalink
feat: thor solo script used for seeding accounts (#278)
Browse files Browse the repository at this point in the history
* feat: thor solo script used for seeding accounts

* refactor: using hex decimal string instead of number for vet value clauses

* docs: thor-solo custom data snapshot in readme

* chore: test origin head

* chore: restore change

* docs: added example file reference

---------

Co-authored-by: Fabio Rigamonti <[email protected]>
  • Loading branch information
pierobassa and fabiorigam authored Nov 21, 2023
1 parent 7745922 commit 771d3eb
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 2 deletions.
39 changes: 37 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,43 @@
- **Lint**: Execute `yarn lint` to lint all packages.
- **Format**: Execute `yarn format` to format all packages.

### Integration Testing
Ensure Docker is running on your machine. The integration tests are performed against a local thor-solo node.
## Integration Testing

This section provides guidance on conducting integration tests using a local thor-solo node. Ensure Docker is operational on your system before proceeding.

### Setting Up
The integration tests interact with a local thor-solo node. This node utilizes the `thor-solo/instance-a4988aba7aea69f6-v3/main.db` data directory, which is pre-configured with a block history and 20 seeded accounts for testing.

### Running Tests
1. **Start the thor-solo node**: Ensure Docker is running and execute the script to launch the thor-solo node.
2. **Run tests**: Use `yarn test:integration` to execute integration tests. These tests are designed to interact with the thor-solo node, verifying the correct operation of various SDK functionalities.

### Custom thor-solo Data Starting Point

For advanced testing scenarios, you may require a custom data starting point with thor-solo. This involves creating a custom snapshot of thor's LevelDB.

#### Creating a Custom LevelDB Snapshot
1. **Start thor-solo with Persistence**:
- Launch thor-solo using Docker with the `--persist` flag. This enables data persistence.
- Use the `--data-dir` flag to specify the directory where thor-solo will store its data.

2. **Perform Transactions**:
- Execute the necessary transactions or operations in thor-solo. These transactions will be recorded in the specified data directory.
- An example of transactions performed to seed the 20 accounts is found in the `thor-solo-seeding.ts` file

3. **Export LevelDB**:
- Once you've completed the transactions, use a tool like `docker cp` to export the LevelDB directory (i.e., `instance-a4988aba7aea69f6-v3`) from the Docker container.

#### Using the Custom Snapshot
1. **Prepare the Dockerfile**:
- Modify the Dockerfile used for building the thor-solo container. Ensure it copies the exported LevelDB snapshot into the correct path within the container.

2. **Update Data Directory Path**:
- Adjust the `--data-dir` flag in your thor-solo startup script or Docker command to point to the new LevelDB snapshot location within the container.

3. **Restart thor-solo**:
- Rebuild and restart the thor-solo container with the updated Dockerfile. This will launch thor-solo with your custom data starting point.


## Documentation and Examples
- The `./docs` directory houses extensive code examples written as executable demonstrations.
Expand Down
102 changes: 102 additions & 0 deletions packages/network/tests/thor-solo-seeding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import {
Transaction,
TransactionHandler,
contract,
unitsUtils
} from '@vechainfoundation/vechain-sdk-core';
import { ALL_ACCOUNTS, soloNetwork } from './fixture';
import { BUILT_IN_CONTRACTS } from './built-in-fixture';
import { ThorestClient } from '../src';

/**
* Constructs clauses for transferring VTHO tokens.
*
* @remarks
* This constant creates an array of transaction clauses for transferring VTHO tokens
* from the built-in energy contract to the first 10 accounts in the `ALL_ACCOUNTS` array.
*/
const CLAUSES_VTHO = ALL_ACCOUNTS.slice(0, 10).map((account) => ({
to: BUILT_IN_CONTRACTS.ENERGY_ADDRESS,
value: 0,
data: contract.encodeFunctionInput(
BUILT_IN_CONTRACTS.ENERGY_ABI,
'transfer',
[account.address, unitsUtils.parseVET('500000000')]
)
}));

/**
* Constructs clauses for transferring VET tokens.
*
* @remarks
* This constant creates an array of transaction clauses for transferring VET tokens
* to the first 10 accounts in the `ALL_ACCOUNTS` array.
*/
const CLAUSES_VET = ALL_ACCOUNTS.slice(0, 10).map((account) => ({
to: account.address,
value: `0x${unitsUtils.parseVET('500000000').toString(16)}`,
data: '0x'
}));

/**
* Constructs a transaction body.
*
* @remarks blockRef is set to the genesis block ref. Expiration is set to 100000 blocks as an example but can be set to any value.
* gas is set to 100000 as an example but can be set to a estimated gas value when the functionality is implemented.
*/
const txBody = {
chainTag: 246,
blockRef: '0x0000000000000000',
expiration: 100000,
gasPriceCoef: 0,
gas: 100000,
dependsOn: null,
nonce: '0x851fd66f'
};

/**
* Array of transaction bodies with clauses for VTHO and VET transfers.
*/
const txBodies = CLAUSES_VTHO.map((clause, index) => ({
...txBody,
clauses: [clause, CLAUSES_VET[index]]
}));

/**
* Array of unsigned transactions.
*/
const unsignedTxs = txBodies.map((txBody) => new Transaction(txBody));

/**
* Array of signed transactions where each transaction is being signed and performed by each of the 10 thor-solo pre-seeded accounts.
*/
const txs = unsignedTxs.map((unsignedTx, index) =>
TransactionHandler.sign(
unsignedTx,
Buffer.from(ALL_ACCOUNTS[10 + index].privateKey, 'hex') // 10 is the index of the first thor-solo genesis account
)
);

/**
* Distributes balances of VTHO and VET to the first 10 accounts.
*
* @remarks
* This function signs and sends transactions to distribute VTHO and VET tokens
* to the first 10 accounts in the `ALL_ACCOUNTS` array. It uses the ThorestClient
* to interact with the VechainThor blockchain.
*
* @returns A Promise that resolves when all transactions have been processed.
*/
const distributeBalances = async (): Promise<void> => {
const thorestSoloClient = new ThorestClient(soloNetwork);

for (const tx of txs) {
const resp = await thorestSoloClient.transactions.sendTransaction(
`0x${tx.encoded.toString('hex')}`
);

console.log(resp.id); // Print the transaction id
}
};

export { distributeBalances };

1 comment on commit 771d3eb

@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 17s ⏱️
network 71 0 💤 0 ❌ 0 🔥 41.034s ⏱️
errors 30 0 💤 0 ❌ 0 🔥 9.89s ⏱️

Please sign in to comment.