From ac456616db9ab4a949053c56d6a42a7e21ae5405 Mon Sep 17 00:00:00 2001 From: elsvv Date: Sat, 26 Oct 2024 16:35:55 +0300 Subject: [PATCH] feat: add tonapi adapter to provider api --- package.json | 2 ++ src/config/CustomNetwork.ts | 2 +- src/network/NetworkProvider.ts | 5 +++- src/network/createNetworkProvider.ts | 43 +++++++++++++++++++--------- src/network/send/MnemonicProvider.ts | 17 +++++++---- yarn.lock | 30 +++++++++++++++++++ 6 files changed, 78 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 5f9ba3e..400b10b 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,8 @@ }, "dependencies": { "@tact-lang/compiler": "^1.4.0", + "@ton-api/client": "^0.2.0", + "@ton-api/ton-adapter": "^0.2.0", "@ton-community/func-js": "^0.7.0", "@tonconnect/sdk": "^2.2.0", "arg": "^5.0.2", diff --git a/src/config/CustomNetwork.ts b/src/config/CustomNetwork.ts index be29e8f..d8a75c1 100644 --- a/src/config/CustomNetwork.ts +++ b/src/config/CustomNetwork.ts @@ -1,6 +1,6 @@ export type CustomNetwork = { endpoint: string; - version?: 'v2' | 'v4'; + version?: 'v2' | 'v4' | 'tonapi'; key?: string; type?: 'mainnet' | 'testnet' | 'custom'; }; diff --git a/src/network/NetworkProvider.ts b/src/network/NetworkProvider.ts index 56a9f04..059755a 100644 --- a/src/network/NetworkProvider.ts +++ b/src/network/NetworkProvider.ts @@ -1,11 +1,14 @@ import { TonClient, TonClient4 } from '@ton/ton'; import { Address, Cell, Contract, ContractProvider, OpenedContract, Sender } from '@ton/core'; +import { ContractAdapter } from '@ton-api/ton-adapter'; import { UIProvider } from '../ui/UIProvider'; +export type BlueprintTonClient = TonClient4 | TonClient | ContractAdapter; + export interface NetworkProvider { network(): 'mainnet' | 'testnet' | 'custom'; sender(): Sender; - api(): TonClient4 | TonClient; + api(): BlueprintTonClient; provider(address: Address, init?: { code?: Cell; data?: Cell }): ContractProvider; isContractDeployed(address: Address): Promise; waitForDeploy(address: Address, attempts?: number, sleepDuration?: number): Promise; diff --git a/src/network/createNetworkProvider.ts b/src/network/createNetworkProvider.ts index 4d4b3aa..6d3754d 100644 --- a/src/network/createNetworkProvider.ts +++ b/src/network/createNetworkProvider.ts @@ -19,8 +19,10 @@ import { TupleItem, } from '@ton/core'; import { TonClient, TonClient4 } from '@ton/ton'; +import { ContractAdapter } from '@ton-api/ton-adapter'; +import { TonApiClient } from '@ton-api/client'; import { UIProvider } from '../ui/UIProvider'; -import { NetworkProvider } from './NetworkProvider'; +import { BlueprintTonClient, NetworkProvider } from './NetworkProvider'; import { SendProvider } from './send/SendProvider'; import { FSStorage } from './storage/FSStorage'; import path from 'path'; @@ -144,13 +146,13 @@ class WrappedContractProvider implements ContractProvider { } class NetworkProviderImpl implements NetworkProvider { - #tc: TonClient4 | TonClient; + #tc: BlueprintTonClient; #sender: Sender; #network: Network; #explorer: Explorer; #ui: UIProvider; - constructor(tc: TonClient4 | TonClient, sender: Sender, network: Network, explorer: Explorer, ui: UIProvider) { + constructor(tc: BlueprintTonClient, sender: Sender, network: Network, explorer: Explorer, ui: UIProvider) { this.#tc = tc; this.#sender = sender; this.#network = network; @@ -170,22 +172,25 @@ class NetworkProviderImpl implements NetworkProvider { return this.#sender; } - api(): TonClient4 | TonClient { + api(): BlueprintTonClient { return this.#tc; } provider(address: Address, init?: StateInit | null): ContractProvider { const factory = (params: { address: Address; init?: StateInit | null }) => - this.#tc.provider(params.address, params.init); + this.#tc.provider( + params.address, + params.init && { + ...params.init, + data: params.init.data ?? undefined, + code: params.init.code ?? undefined, + }, + ); return new WrappedContractProvider(address, factory, init); } async isContractDeployed(address: Address): Promise { - if (this.#tc instanceof TonClient4) { - return this.#tc.isContractDeployed((await this.#tc.getLastBlock()).last.seqno, address); - } else { - return (await this.#tc.getContractState(address)).state === 'active'; - } + return (await this.#tc.provider(address).getState()).state.type === 'active'; } async waitForDeploy(address: Address, attempts: number = 20, sleepDuration: number = 2000) { @@ -247,7 +252,7 @@ class NetworkProviderImpl implements NetworkProvider { } } -async function createMnemonicProvider(client: TonClient4 | TonClient, ui: UIProvider) { +async function createMnemonicProvider(client: BlueprintTonClient, ui: UIProvider) { const mnemonic = process.env.WALLET_MNEMONIC ?? ''; const walletVersion = process.env.WALLET_VERSION ?? ''; if (mnemonic.length === 0 || walletVersion.length === 0) { @@ -310,7 +315,7 @@ class NetworkProviderBuilder { ); } - async chooseSendProvider(network: Network, client: TonClient4 | TonClient): Promise { + async chooseSendProvider(network: Network, client: BlueprintTonClient): Promise { let deployUsing = oneOrZeroOf({ tonconnect: this.args['--tonconnect'], deeplink: this.args['--deeplink'], @@ -382,7 +387,7 @@ class NetworkProviderBuilder { } if (this.args['--custom'] !== undefined) { const inputVer = this.args['--custom-version']; - let version: 'v4' | 'v2' | undefined = undefined; + let version: CustomNetwork['version'] = undefined; if (inputVer !== undefined) { version = inputVer.toLowerCase() as any; // checks come later } @@ -413,6 +418,13 @@ class NetworkProviderBuilder { tc = new TonClient4({ endpoint: configNetwork.endpoint, }); + } else if (configNetwork.version === 'tonapi') { + tc = new ContractAdapter( + new TonApiClient({ + baseUrl: configNetwork.endpoint, + apiKey: configNetwork.key, + }), + ); } else { throw new Error('Unknown API version: ' + configNetwork.version); } @@ -450,7 +462,10 @@ class NetworkProviderBuilder { }; tc = new TonClient({ - endpoint: network === 'mainnet' ? 'https://toncenter.com/api/v2/jsonRPC' : 'https://testnet.toncenter.com/api/v2/jsonRPC', + endpoint: + network === 'mainnet' + ? 'https://toncenter.com/api/v2/jsonRPC' + : 'https://testnet.toncenter.com/api/v2/jsonRPC', httpAdapter, }); } diff --git a/src/network/send/MnemonicProvider.ts b/src/network/send/MnemonicProvider.ts index a4e8a3e..065f02e 100644 --- a/src/network/send/MnemonicProvider.ts +++ b/src/network/send/MnemonicProvider.ts @@ -1,6 +1,4 @@ import { - TonClient, - TonClient4, WalletContractV1R1, WalletContractV1R2, WalletContractV1R3, @@ -25,6 +23,7 @@ import { import { SendProvider } from './SendProvider'; import { keyPairFromSecretKey } from '@ton/crypto'; import { UIProvider } from '../../ui/UIProvider'; +import { BlueprintTonClient } from '../NetworkProvider'; interface WalletInstance extends Contract { getSeqno(provider: ContractProvider): Promise; @@ -62,14 +61,14 @@ const wallets: Record = { export class MnemonicProvider implements SendProvider { #wallet: OpenedContract; #secretKey: Buffer; - #client: TonClient4 | TonClient; + #client: BlueprintTonClient; #ui: UIProvider; constructor(params: { version: WalletVersion; workchain?: number; secretKey: Buffer; - client: TonClient4 | TonClient; + client: BlueprintTonClient; ui: UIProvider; }) { if (!(params.version in wallets)) { @@ -83,7 +82,15 @@ export class MnemonicProvider implements SendProvider { workchain: params.workchain ?? 0, publicKey: kp.publicKey, }), - (params) => this.#client.provider(params.address, params.init), + (params) => + this.#client.provider( + params.address, + params.init && { + ...params.init, + data: params.init.data ?? undefined, + code: params.init.code ?? undefined, + }, + ), ); this.#secretKey = kp.secretKey; this.#ui = params.ui; diff --git a/yarn.lock b/yarn.lock index 436f9f0..d35765b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -172,6 +172,27 @@ __metadata: languageName: node linkType: hard +"@ton-api/client@npm:^0.2.0": + version: 0.2.0 + resolution: "@ton-api/client@npm:0.2.0" + dependencies: + core-js-pure: "npm:^3.38.0" + peerDependencies: + "@ton/core": ">=0.59.0" + checksum: 10/a625c8e896cecacae04390dc3e948f7050354950ec47bc303b32594716ff31071dc50b8047ff2e6d0aa27ae4c70c4369dfad8b4a17b401a40996044c4e993dbd + languageName: node + linkType: hard + +"@ton-api/ton-adapter@npm:^0.2.0": + version: 0.2.0 + resolution: "@ton-api/ton-adapter@npm:0.2.0" + peerDependencies: + "@ton-api/client": ^0.2.0 + "@ton/core": ">=0.59.0" + checksum: 10/121f07ceefd3a0e1c9ed08e8cd5f6ced8f8a2471f809eb5f4c80ca11418a3be216ab38fa7f1499aa1d4af3e2a0f01d0c829d290b9a6c66c178e7c8ab8071d24b + languageName: node + linkType: hard + "@ton-community/func-js-bin@npm:0.4.4-newops.1": version: 0.4.4-newops.1 resolution: "@ton-community/func-js-bin@npm:0.4.4-newops.1" @@ -196,6 +217,8 @@ __metadata: resolution: "@ton/blueprint@workspace:." dependencies: "@tact-lang/compiler": "npm:^1.4.0" + "@ton-api/client": "npm:^0.2.0" + "@ton-api/ton-adapter": "npm:^0.2.0" "@ton-community/func-js": "npm:^0.7.0" "@ton/core": "npm:^0.58.1" "@ton/crypto": "npm:^3.3.0" @@ -681,6 +704,13 @@ __metadata: languageName: node linkType: hard +"core-js-pure@npm:^3.38.0": + version: 3.38.1 + resolution: "core-js-pure@npm:3.38.1" + checksum: 10/7dfd59bf3a09277056ac2ef87e49b49d77340952e99ee12b3e1e53bf7e1f34a8ee1fb6026f286b1ba29957f5728664430ccd1ff86983c7ae5fa411d4da74d3de + languageName: node + linkType: hard + "create-require@npm:^1.1.0": version: 1.1.1 resolution: "create-require@npm:1.1.1"