Add deploy script for HighloadWalletV3 contract#20
Conversation
This script estimates the deploy amount for a HighloadWalletV3 contract and computes its address. It includes safety checks for deployment and allows for dynamic fee estimation.
There was a problem hiding this comment.
Pull request overview
This PR adds a deployment script for the HighloadWalletV3 contract that computes the contract address and estimates deployment costs. The script includes safety mechanisms to prevent accidental deployments and supports dynamic fee estimation with fallback options.
Changes:
- Adds a TypeScript deployment script with configurable environment variables for contract deployment
- Implements fee estimation logic with TonClient integration and fallback values
- Includes safety checks requiring explicit CONFIRM_DEPLOY flag before any network operations
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Fallback to default conservative amount | ||
| console.log('Using fallback deploy value:', DEPLOY_FALLBACK, 'TON'); | ||
| const fallback = toNano(DEPLOY_FALLBACK); | ||
| const withMargin = BigInt(Math.ceil(Number(fallback) * DEPLOY_SAFE_MARGIN)); |
There was a problem hiding this comment.
Converting bigint to number for multiplication can cause precision loss for large values. Since fallback is already a bigint from toNano(), consider using BigInt arithmetic throughout: const withMargin = (fallback * BigInt(Math.floor(DEPLOY_SAFE_MARGIN * 1000))) / 1000n to maintain precision.
|
|
||
| // TODO: replace this placeholder with deriving the actual publicKey from your secret key | ||
| // For now we use a zeroed publicKey buffer as placeholder to compute address deterministically | ||
| const publicKeyPlaceholder = Buffer.alloc(32, 0); |
There was a problem hiding this comment.
Using a zeroed placeholder public key will result in computing an incorrect contract address. The address depends on the actual public key that will be used for deployment. This means the computed address will not match the actual deployed contract address if a different public key is used later, which could lead to funds being sent to the wrong address or deployment failures.
| const DEPLOY_FALLBACK = process.env.DEPLOY_FALLBACK || '0.1'; | ||
| const CONFIRM_DEPLOY = process.env.CONFIRM_DEPLOY === 'true'; // must be explicitly set to "true" to send | ||
|
|
||
| async function estimateDeployAmount(init: any): Promise<bigint> { |
There was a problem hiding this comment.
The function accepts 'any' type for the init parameter, which bypasses type safety. Consider defining a proper interface or type for the init parameter, such as: { code: Cell, data: Cell } to ensure type safety and better IDE support.
fix for @ton/ton scripts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
fix for deploy scripts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@LucasL160 I've opened a new pull request, #24, to work on those changes. Once the pull request is ready, I'll request review from you. |
|
@LucasL160 I've opened a new pull request, #25, to work on those changes. Once the pull request is ready, I'll request review from you. |
deploy script fix Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
Copilot open a new pull request to apply changes based on the comments in this thread |
|
@LucasL160 I've opened a new pull request, #26, to work on those changes. Once the pull request is ready, I'll request review from you. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| console.warn('TonClient found but no known estimate method present. Falling back.'); | ||
| } catch (e) { | ||
| console.warn( | ||
| 'Could not use TonClient to estimate fees (skipped). Error:', |
There was a problem hiding this comment.
Precision loss when converting BigInt to Number. When converting fallback (a BigInt) to Number for multiplication, very large values could lose precision. The safer approach is to perform the multiplication in BigInt arithmetic directly:
const withMargin = (fallback * BigInt(Math.floor(DEPLOY_SAFE_MARGIN * 100))) / 100n;This preserves BigInt precision throughout the calculation.
|
|
||
| const SUBWALLET_ID = Number(process.env.SUBWALLET_ID || HIGHLOAD_WALLET_V3_DEFAULT_SUBWALLET_ID); | ||
| const TIMEOUT = Number(process.env.TIMEOUT || 3600); | ||
| const DEPLOY_VALUE_ENV = process.env.DEPLOY_VALUE || ''; |
There was a problem hiding this comment.
The 'any' type for the 'init' parameter reduces type safety. Consider defining a proper interface or using a type from '@ton/core' library, such as:
async function estimateDeployAmount(init: { code: Cell; data: Cell }): Promise<bigint>This provides better type checking and IDE support.
| // dynamic require to avoid TypeScript type errors if library evolves | ||
| // eslint-disable-next-line @typescript-eslint/no-var-requires | ||
| const { TonClient } = require('ton'); | ||
| const client = new TonClient({ endpoint: RPC_URL }); | ||
|
|
There was a problem hiding this comment.
Using require() for dynamic import breaks the ESM module pattern used in the rest of the file. Consider using dynamic import() instead for consistency:
const { TonClient } = await import('ton');This maintains ESM consistency and is more compatible with modern TypeScript/Node.js practices.
| // dynamic require to avoid TypeScript type errors if library evolves | |
| // eslint-disable-next-line @typescript-eslint/no-var-requires | |
| const { TonClient } = require('ton'); | |
| const client = new TonClient({ endpoint: RPC_URL }); | |
| // dynamic import to avoid TypeScript type errors if library evolves | |
| const { TonClient } = await import('ton'); | |
| const client = new TonClient({ endpoint: RPC_URL }); |
| const SECRET_KEY_BASE64 = process.env.SECRET_KEY_BASE64 || ''; | ||
| const WORKCHAIN = Number(process.env.WORKCHAIN || 0); | ||
|
|
||
| // Default subwallet id for HighloadWalletV3 as per the HighloadWalletV3 specification. |
There was a problem hiding this comment.
No validation for TIMEOUT value. The Number() conversion could result in NaN if the environment variable is not a valid number, which would cause issues when creating the config cell. Consider adding validation:
const timeout = Number(process.env.TIMEOUT || 3600);
if (isNaN(timeout)) {
throw new Error('TIMEOUT must be a valid number');
}
const TIMEOUT = timeout;| subwalletId: SUBWALLET_ID, | ||
| timeout: TIMEOUT, | ||
| }); | ||
|
|
There was a problem hiding this comment.
Precision loss when converting BigInt to Number for display. For very large values (near the Number.MAX_SAFE_INTEGER limit), this conversion could lose precision. Consider using a string-based division or a dedicated BigInt formatting function for accurate display.
|
|
||
| // Default subwallet id for HighloadWalletV3 as per the HighloadWalletV3 specification. | ||
| // Can be overridden via the SUBWALLET_ID environment variable if needed. | ||
| const HIGHLOAD_WALLET_V3_DEFAULT_SUBWALLET_ID = 0x10ad; |
There was a problem hiding this comment.
No validation for DEPLOY_SAFE_MARGIN value. If the environment variable contains a non-numeric value or negative number, Number() will return NaN or a negative value, which could cause unexpected behavior in calculations. Consider adding validation:
const margin = Number(process.env.DEPLOY_SAFE_MARGIN || '1.5');
if (isNaN(margin) || margin < 0) {
throw new Error('DEPLOY_SAFE_MARGIN must be a non-negative number');
}
const DEPLOY_SAFE_MARGIN = margin;
This script estimates the deploy amount for a HighloadWalletV3 contract and computes its address. It includes safety checks for deployment and allows for dynamic fee estimation.