From 13d1e72ea98c280e66c249af4180e738fa2618b6 Mon Sep 17 00:00:00 2001 From: siandreev Date: Wed, 27 Sep 2023 16:50:59 +0200 Subject: [PATCH] feat: lib deployment scripts added --- .env.example | 4 ++ .gitignore | 1 + contracts/library-deployer.fc | 19 +++++++++ package.json | 3 ++ scripts/deployLibrary.ts | 54 +++++++++++++++++++++++++ scripts/deployWalletV5.ts | 14 +++++-- scripts/deployWalletV5WithoutLibrary.ts | 28 +++++++++++++ scripts/printWalletCode.ts | 11 +++++ wrappers/library-deployer.compile.ts | 6 +++ wrappers/library-deployer.ts | 41 +++++++++++++++++++ wrappers/wallet-v5.ts | 9 ++++- 11 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 .env.example create mode 100644 contracts/library-deployer.fc create mode 100644 scripts/deployLibrary.ts create mode 100644 scripts/deployWalletV5WithoutLibrary.ts create mode 100644 scripts/printWalletCode.ts create mode 100644 wrappers/library-deployer.compile.ts create mode 100644 wrappers/library-deployer.ts diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..3d3ea2bd --- /dev/null +++ b/.env.example @@ -0,0 +1,4 @@ +WALLET_MNEMONIC= + +# v4 +WALLET_VERSION= diff --git a/.gitignore b/.gitignore index 3df5ddde..ef9f336c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules temp build .idea +.env diff --git a/contracts/library-deployer.fc b/contracts/library-deployer.fc new file mode 100644 index 00000000..3bdbea4f --- /dev/null +++ b/contracts/library-deployer.fc @@ -0,0 +1,19 @@ +#pragma version =0.4.4; +#include "imports/stdlib.fc"; + +() set_lib_code(cell code, int mode) impure asm "SETLIBCODE"; + +() deploy_lib() impure { + set_lib_code(get_data(), 2); + cell empty = begin_cell().end_cell(); + set_code(empty); + set_data(empty); +} + +() recv_internal(slice in_msg) impure { + deploy_lib(); +} + +() recv_external(slice in_msg) impure { + deploy_lib(); +} diff --git a/package.json b/package.json index 2052ad99..59dfb3c3 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,9 @@ "start": "blueprint run", "build": "blueprint build", "build:v5": "blueprint build wallet_v5", + "deploy-library": "npx blueprint run deployLibrary", + "deploy-wallet": "blueprint run deployWalletV5", + "print-wallet-code": "ts-node ./scripts/printWalletCode.ts", "test": "jest" }, "devDependencies": { diff --git a/scripts/deployLibrary.ts b/scripts/deployLibrary.ts new file mode 100644 index 00000000..171241be --- /dev/null +++ b/scripts/deployLibrary.ts @@ -0,0 +1,54 @@ +import { toNano } from 'ton-core'; +import { compile, NetworkProvider } from '@ton-community/blueprint'; +import 'dotenv/config'; +import { LibraryDeployer } from '../wrappers/library-deployer'; + +export async function run(provider: NetworkProvider) { + /* const library: SimpleLibrary = { + public: true, + root: await compile('wallet_v5') + }; + + let secretKey = process.env.LIBRARY_KEEPER_SECRET_KEY; + if (!secretKey) { + const keypair = keyPairFromSeed(await getSecureRandomBytes(32)); + console.log('GENERATED PRIVATE_KEY', keypair.secretKey.toString('hex')); + secretKey = keypair.secretKey.toString('hex'); + fs.appendFileSync('.env', `LIBRARY_KEEPER_SECRET_KEY=${secretKey}`); + } + + const keypair = keyPairFromSecretKey(Buffer.from(secretKey, 'hex')); + + const libraryKeeper = provider.open( + LibraryKeeper.createFromConfig( + { publicKey: keypair.publicKey, seqno: 0 }, + await compile('library-keeper') + ) + ); + + const isActive = await libraryKeeper.getIsActive(); + + if (!isActive) { + await libraryKeeper.sendDeploy(provider.sender(), toNano('0.1')); + await provider.waitForDeploy(libraryKeeper.address); + } + + await libraryKeeper.sendAddLibrary({ + libraryCode: library.root, + secretKey: keypair.secretKey + }); + + console.log('LIBRARY KEEPER ADDRESS', libraryKeeper.address);*/ + + const libraryDeployer = provider.open( + LibraryDeployer.createFromConfig( + { libraryCode: await compile('wallet_v5') }, + await compile('library-deployer') + ) + ); + + await libraryDeployer.sendDeploy(provider.sender(), toNano('0.1')); + await provider.waitForDeploy(libraryDeployer.address); + + console.log('LIBRARY ADDRESS', libraryDeployer.address); +} diff --git a/scripts/deployWalletV5.ts b/scripts/deployWalletV5.ts index f0cf632e..b081046b 100644 --- a/scripts/deployWalletV5.ts +++ b/scripts/deployWalletV5.ts @@ -2,9 +2,17 @@ import { Dictionary, toNano } from 'ton-core'; import { WalletId, WalletV5 } from '../wrappers/wallet-v5'; import { compile, NetworkProvider } from '@ton-community/blueprint'; import { getSecureRandomBytes, keyPairFromSeed } from 'ton-crypto'; +import 'dotenv/config'; +import { LibraryKeeper } from '../wrappers/library-keeper'; +import {randomTestKey} from "ton/dist/utils/randomTestKey"; +/* + DOESN'T WORK WITH TONKEEPER AND TONCONNECT. CHOOSE DEPLOY WITH MNEMONIC + */ export async function run(provider: NetworkProvider) { - const keypair = keyPairFromSeed(await getSecureRandomBytes(32)); + const keypair = randomTestKey('v5-treasure'); // keyPairFromSeed( + //await getSecureRandomBytes(32) + //); console.log('KEYPAIR PUBKEY', keypair.publicKey.toString('hex')); console.log('KEYPAIR PRIVATE_KEY', keypair.secretKey.toString('hex')); @@ -16,11 +24,11 @@ export async function run(provider: NetworkProvider) { publicKey: keypair.publicKey, extensions: Dictionary.empty() }, - await compile('wallet_v5') + LibraryKeeper.exportLibCode(await compile('wallet_v5')) ) ); - await walletV5.sendDeploy(provider.sender(), toNano('0.05')); + await walletV5.sendDeploy(provider.sender(), toNano('0.1')); await provider.waitForDeploy(walletV5.address); diff --git a/scripts/deployWalletV5WithoutLibrary.ts b/scripts/deployWalletV5WithoutLibrary.ts new file mode 100644 index 00000000..f0cf632e --- /dev/null +++ b/scripts/deployWalletV5WithoutLibrary.ts @@ -0,0 +1,28 @@ +import { Dictionary, toNano } from 'ton-core'; +import { WalletId, WalletV5 } from '../wrappers/wallet-v5'; +import { compile, NetworkProvider } from '@ton-community/blueprint'; +import { getSecureRandomBytes, keyPairFromSeed } from 'ton-crypto'; + +export async function run(provider: NetworkProvider) { + const keypair = keyPairFromSeed(await getSecureRandomBytes(32)); + console.log('KEYPAIR PUBKEY', keypair.publicKey.toString('hex')); + console.log('KEYPAIR PRIVATE_KEY', keypair.secretKey.toString('hex')); + + const walletV5 = provider.open( + WalletV5.createFromConfig( + { + seqno: 0, + walletId: new WalletId({ networkGlobalId: -3 }).serialized, // testnet + publicKey: keypair.publicKey, + extensions: Dictionary.empty() + }, + await compile('wallet_v5') + ) + ); + + await walletV5.sendDeploy(provider.sender(), toNano('0.05')); + + await provider.waitForDeploy(walletV5.address); + + console.log('ADDRESS', walletV5.address); +} diff --git a/scripts/printWalletCode.ts b/scripts/printWalletCode.ts new file mode 100644 index 00000000..9ed3491d --- /dev/null +++ b/scripts/printWalletCode.ts @@ -0,0 +1,11 @@ +import { compile } from '@ton-community/blueprint'; +import { LibraryKeeper } from '../wrappers/library-keeper'; + +export async function run() { + const code = LibraryKeeper.exportLibCode(await compile('wallet_v5')); + + console.log('WALLET CODE HEX', code.toBoc().toString('hex'), '\n'); + console.log('WALLET CODE BASE64', code.toBoc().toString('base64')); +} + +run(); diff --git a/wrappers/library-deployer.compile.ts b/wrappers/library-deployer.compile.ts new file mode 100644 index 00000000..77534c83 --- /dev/null +++ b/wrappers/library-deployer.compile.ts @@ -0,0 +1,6 @@ +import { CompilerConfig } from '@ton-community/blueprint'; + +export const compile: CompilerConfig = { + lang: 'func', + targets: ['contracts/library-deployer.fc'] +}; diff --git a/wrappers/library-deployer.ts b/wrappers/library-deployer.ts new file mode 100644 index 00000000..1441b0e7 --- /dev/null +++ b/wrappers/library-deployer.ts @@ -0,0 +1,41 @@ +import { + Address, + beginCell, + BitBuilder, + Cell, + Contract, + contractAddress, + ContractProvider, + Sender, + SendMode +} from 'ton-core'; + +export type LibraryDeployerConfig = { + libraryCode: Cell; +}; + +export class LibraryDeployer implements Contract { + static exportLibCode(code: Cell) { + const bits = new BitBuilder(); + bits.writeUint(2, 8); + bits.writeUint(BigInt('0x' + code.hash().toString('hex')), 256); + + return new Cell({ exotic: true, bits: bits.build() }); + } + + constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {} + + static createFromConfig(config: LibraryDeployerConfig, code: Cell, workchain = -1) { + const data = config.libraryCode; + const init = { code, data }; + return new LibraryDeployer(contractAddress(workchain, init), init); + } + + async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) { + await provider.internal(via, { + value, + sendMode: SendMode.PAY_GAS_SEPARATELY, + body: beginCell().endCell() + }); + } +} diff --git a/wrappers/wallet-v5.ts b/wrappers/wallet-v5.ts index e00f403f..1eca81b5 100644 --- a/wrappers/wallet-v5.ts +++ b/wrappers/wallet-v5.ts @@ -184,8 +184,13 @@ export class WalletV5 implements Contract { } async getSeqno(provider: ContractProvider) { - const result = await provider.get('seqno', []); - return result.stack.readNumber(); + const state = await provider.getState(); + if (state.state.type === 'active') { + let res = await provider.get('seqno', []); + return res.stack.readNumber(); + } else { + return 0; + } } async getWalletId(provider: ContractProvider) {