Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
106f3ef
refactor: implement {data, error} response pattern
mois-ilya Nov 10, 2025
842fc56
feat: add schema patching system for OpenAPI client generation
mois-ilya Nov 10, 2025
3358e7c
feat: enhance HttpClient with API key management and custom fetch sup…
mois-ilya Nov 10, 2025
c7c718e
feat: implement centralized error handling for parsing errors in TonA…
mois-ilya Nov 11, 2025
df0c0d9
refactor: enhance error handling in TonAPI SDK
mois-ilya Nov 11, 2025
bdc7c8e
refactor: update TonApi client initialization and method usage
mois-ilya Nov 11, 2025
b54376d
feat: update API schema and enhance client functionality
mois-ilya Nov 11, 2025
dc86a60
chore: bump version to 0.5.0-alpha.0 in package.json and update clien…
mois-ilya Nov 11, 2025
58044f8
refactor: enhance TonApi client structure and error handling
mois-ilya Nov 13, 2025
abecfca
chore: bump version to 0.5.0-alpha.1
mois-ilya Nov 13, 2025
0a0a6b5
refactor: update examples to use TonApiClient instance
mois-ilya Nov 13, 2025
5abc4c6
chore: bump version to 0.5.0-alpha.2 in package.json and client packa…
mois-ilya Nov 13, 2025
7f3fe05
refactor: update address format to maybe-address in API schema and cl…
mois-ilya Nov 13, 2025
bb6cccc
chore: bump version to 0.5.0-alpha.3 in package.json and client packa…
mois-ilya Nov 13, 2025
d7f704c
feat: add typed error handling and address string support
mois-ilya Nov 14, 2025
9b28f2a
feat: add client-side validation and fix typed error handling
mois-ilya Nov 14, 2025
0de0bc7
chore: bump version to 0.5.0-alpha.6 in package.json and client packa…
mois-ilya Nov 14, 2025
f07dd34
feat: enhance API schema and client functionality
mois-ilya Nov 18, 2025
12feed0
fix: update JettonTransferPayload schema to use cell format for custo…
mois-ilya Nov 18, 2025
3c1a8c8
test: improve coverage with parsing tests and fix mock fetch
mois-ilya Dec 4, 2025
8b0d704
chore: bump version to 0.5.0-alpha.7
mois-ilya Dec 4, 2025
83f12af
chore(client): fix type for extra field and improve descriptions
mois-ilya Dec 10, 2025
6477ffb
chore: bump version to 0.5.0-alpha.8
mois-ilya Dec 10, 2025
fef0e20
fix(client): correct BlockchainConfig code_hash type from Address to …
mois-ilya Dec 22, 2025
363037e
chore: bump version to 0.5.0-alpha.9
mois-ilya Dec 22, 2025
3bbf469
fix(client): add stack trace to parsing error console output
mois-ilya Dec 22, 2025
f508238
chore: bump version to 0.5.1 and update API schema
rAndom1zeeeR Jun 19, 2026
965f7ab
fix(client): update response data structure for slice and builder types
rAndom1zeeeR Jun 19, 2026
6f4bb5b
chore: bump version to 0.5.1 and update changelog
rAndom1zeeeR Jun 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 67 additions & 29 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,102 @@

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/).
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

## [0.5.1] - 2026-06-20

### Fixed

- **TupleItem slice parsing**: map API `slice` values to `@ton/core`-compatible `cell` field
(fixes `TupleReader.readCell()` in adapter)
- **Duplicate JSDoc** on deprecated class methods in generated client
- **Schema download**: validate HTTP status and handle redirects in `update-schema`
- **Monorepo build**: resolve workspace `@ton-api/client` in `@ton-api/ton-adapter` (no stale
0.4.0 types)

### Changed

- **OpenAPI schema** regenerated from latest TonAPI (`api.yml`, `client.ts`)
- **Client build**: `tsc` replaced with `tsup` (dual CJS + ESM output)
- **Client package.json**: added `exports` and `module` fields
- **Build scripts**: split `generate` (offline) and `update-schema` (network)
- **Vitest**: resolve `@ton-api/client` from `src/` without pre-build
- **Turbo**: explicit build inputs; client `clean` removed from build pipeline
- **Workspaces**: exclude unfinished `@ton-api/sdk` package
- **@ton-api/ton-adapter** bumped to `0.5.1`

## [0.4.1] - 2025-04-23

### Fixed
- Fixed package.json configuration in `@ton-api/ton-adapter` where prepublishOnly script was incorrectly placed in peerDependencies section

- Fixed package.json configuration in `@ton-api/ton-adapter` where prepublishOnly script was
incorrectly placed in peerDependencies section

### Changed
- Migrated all tests from Jest to Vitest and moved them to a separate directory for better organization
- Configured Turbopack for improved build performance

- Migrated all tests from Jest to Vitest and moved them to a separate directory for better
organization
- Configured Turbopack for improved build performance

## [0.4.0] - 2025-01-29

### Fixed
- **Key Formatting (like Addresses)**: address keys and other additional fields retain their original formatting without converting to camelCase, maintaining data consistency and preventing key mismatches (https://github.com/tonkeeper/tonapi-js/issues/222)
- **Memory Leak**: Fixed a memory leak caused by the `clone` method in API requests, enhancing performance and stability. (https://github.com/tonkeeper/tonapi-js/issues/212)
- **Query Parameter Handling**: add support for `explode: false` in query parameters, ensuring accurate API request generation. (https://github.com/tonkeeper/tonapi-js/issues/221)

- **Key Formatting (like Addresses)**: address keys and other additional fields retain their
original formatting without converting to camelCase, maintaining data consistency and preventing
key mismatches (https://github.com/tonkeeper/tonapi-js/issues/222)
- **Memory Leak**: Fixed a memory leak caused by the `clone` method in API requests, enhancing
performance and stability. (https://github.com/tonkeeper/tonapi-js/issues/212)
- **Query Parameter Handling**: add support for `explode: false` in query parameters, ensuring
accurate API request generation. (https://github.com/tonkeeper/tonapi-js/issues/221)

### Improved
- **Error Handling**: Changed priority of error handling to ensure that the error message is returned, if available, instead of the error code. This change provides more context to the user and helps in debugging.

- **Error Handling**: Changed priority of error handling to ensure that the error message is
returned, if available, instead of the error code. This change provides more context to the user
and helps in debugging.

## [0.3.1] - 2025-01-09

### Added
- Support for prefixItems from openapi 3.1.0 in schema
- Example for using Emulation in the client

- Support for prefixItems from openapi 3.1.0 in schema
- Example for using Emulation in the client

### Fixed
- Corrected type mismatch for operations with inline response schemas (not defined via $ref in components) in OpenAPI. Key transformations from snake_case to camelCase are now properly reflected in the types, making them usable.
- Resolved an internal issue that caused generation failures when the response format was not application/json.

- Corrected type mismatch for operations with inline response schemas (not defined via $ref in
components) in OpenAPI. Key transformations from snake_case to camelCase are now properly
reflected in the types, making them usable.
- Resolved an internal issue that caused generation failures when the response format was not
application/json.

## [0.3.0] - 2024-11-19

### Fixed
- Fixed issue where errors without a json method or with invalid JSON responses caused unhandled exceptions [#37](https://github.com/tonkeeper/tonapi-js/pull/37)
- Properly apply custom fetch from ApiConfig [#201](https://github.com/tonkeeper/tonapi-js/issues/201)

- Fixed issue where errors without a json method or with invalid JSON responses caused unhandled
exceptions [#37](https://github.com/tonkeeper/tonapi-js/pull/37)
- Properly apply custom fetch from ApiConfig
[#201](https://github.com/tonkeeper/tonapi-js/issues/201)

## [0.2.0] - 2024-10-18

### Added
- Conversion of relevant strings to `bigint` alongside large numerical values.
- Response types for the `getChartRates` operation.
- Mechanism for free requests to `tonapi` through the client, providing this capability to dApps.
- `x-tonapi-client` header for requests specifying the client version.

- Simplified client initialization process using a single initializer.
- Parsing of API errors to eliminate the need for boilerplate code.
- Conversion of relevant strings to `bigint` alongside large numerical values.
- Response types for the `getChartRates` operation.
- Mechanism for free requests to `tonapi` through the client, providing this capability to dApps.
- `x-tonapi-client` header for requests specifying the client version.

- Simplified client initialization process using a single initializer.
- Parsing of API errors to eliminate the need for boilerplate code.

## [0.1.0] - 2024-08-16

### Added
- Initial release of the `@ton-api/client` with basic API interaction functions.

## [Unreleased]

### Changed
- Migrated all tests from Jest to Vitest for better performance and modern testing experience

### Added
- Description of future changes.
- Initial release of the `@ton-api/client` with basic API interaction functions.
31 changes: 25 additions & 6 deletions examples/emulate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,38 @@ import {
import { mnemonicNew, mnemonicToPrivateKey } from '@ton/crypto';
import { TonApiClient } from '@ton-api/client';

// Create TonApiClient instance
// if you need to send lots of requests in parallel, make sure you use a tonapi token.
const ta = new TonApiClient({
const tonApiClient = new TonApiClient({
baseUrl: 'https://tonapi.io',
apiKey: 'YOUR_API_KEY'
// apiKey: 'YOUR_API_KEY'
});

// Sender's wallet address
const senderAddress = Address.parse('UQAQxxpzxmEVU0Lu8U0zNTxBzXIWPvo263TIN1OQM9YvxsnV');
const recipientAddress = Address.parse('UQDNzlh0XSZdb5_Qrlx5QjyZHVAO74v5oMeVVrtF_5Vt1rIt');

// Get wallet's seqno and public key
const { seqno } = await ta.wallet.getAccountSeqno(senderAddress);
const { publicKey: publicKeyHex } = await ta.accounts.getAccountPublicKey(senderAddress);
const seqno = await tonApiClient
.getAccountSeqno(senderAddress)
.then(seqnoData => seqnoData.seqno)
.catch((error: unknown) => {
console.error(
'Error getting account seqno:',
error instanceof Error ? error.message : String(error)
);
process.exit(1);
});

const publicKeyHex = await tonApiClient
.getAccountPublicKey(senderAddress)
.then(publicKeyData => publicKeyData.publicKey)
.catch((error: unknown) => {
console.error(
'Error getting account public key:',
error instanceof Error ? error.message : String(error)
);
process.exit(1);
});

// Emulate transaction from wallet_v4 address
const wallet = WalletContractV4.create({
Expand Down Expand Up @@ -73,7 +92,7 @@ const bocExternalMessage = beginCell()
.endCell();

// Emulate transaction
const emulateTrace = await ta.emulation.emulateMessageToTrace(
const emulateTrace = await tonApiClient.emulateMessageToTrace(
{ boc: bocExternalMessage },
{ ignore_signature_check: true } // Ignore signature for execute message from other account
);
Expand Down
63 changes: 43 additions & 20 deletions examples/gasless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ import {
storeMessageRelaxed
} from '@ton/ton';

import { TonApiClient } from '@ton-api/client';
import { TonApiClient, TonApiHttpError } from '@ton-api/client';
import { ContractAdapter } from '@ton-api/ton-adapter';

// Create TonApiClient instance
// if you need to send lots of requests in parallel, make sure you use a tonapi token.
const ta = new TonApiClient({
const tonApiClient = new TonApiClient({
baseUrl: 'https://tonapi.io',
apiKey: 'YOUR_API_KEY'
// apiKey: 'YOUR_API_KEY'
});

const provider = new ContractAdapter(ta);
const provider = new ContractAdapter(tonApiClient);

const OP_CODES = {
TK_RELAYER_FEE: 0x878da6e3,
Expand All @@ -47,13 +48,15 @@ const contract = provider.open(wallet);

console.log('Wallet address:', wallet.address.toString());

const jettonWalletAddressResult = await ta.blockchain.execGetMethodForBlockchainAccount(
usdtMaster,
'get_wallet_address',
{
const jettonWalletAddressResult = await tonApiClient
.execGetMethodForBlockchainAccount(usdtMaster, 'get_wallet_address', {
args: [wallet.address.toRawString()]
}
);
})
.catch((getWalletError: unknown) => {
console.error('Error getting jetton wallet:',
getWalletError instanceof Error ? getWalletError.message : String(getWalletError));
process.exit(1);
});

const jettonWallet = Address.parse(jettonWalletAddressResult.decoded.jetton_wallet_address);

Expand Down Expand Up @@ -90,11 +93,17 @@ const messageToEstimate = beginCell()
// we send a single message containing a transfer from our wallet to a desired destination.
// as a result of estimation, TonAPI returns a list of messages that we need to sign.
// the first message is a fee transfer to the relay address, the second message is our original transfer.
const params = await ta.gasless.gaslessEstimate(usdtMaster, {
walletAddress: wallet.address,
walletPublicKey: keyPair.publicKey.toString('hex'),
messages: [{ boc: messageToEstimate }]
}); //.catch(error => console.error(error));
const params = await tonApiClient
.gaslessEstimate(usdtMaster, {
walletAddress: wallet.address,
walletPublicKey: keyPair.publicKey.toString('hex'),
messages: [{ boc: messageToEstimate }]
})
.catch((estimateError: unknown) => {
console.error('Error estimating gasless transfer:',
estimateError instanceof Error ? estimateError.message : String(estimateError));
process.exit(1);
});

console.log('Estimated transfer:', params);

Expand Down Expand Up @@ -129,19 +138,33 @@ const extMessage = beginCell()
.endCell();

// Send a gasless transfer
ta.gasless
const sendResult = await tonApiClient
.gaslessSend({
walletPublicKey: keyPair.publicKey.toString('hex'),
boc: extMessage
})
.then(() => console.log('A gasless transfer sent!'))
.catch(error => console.error(error.message));
.catch((sendError: unknown) => {
if (sendError instanceof TonApiHttpError) {
console.error('Error sending gasless transfer:', sendError.message, 'Status:', sendError.status);
} else {
console.error('Error sending gasless transfer:', sendError instanceof Error ? sendError.message : String(sendError));
}
return null;
});

if (sendResult) {
console.log('A gasless transfer sent!');
}

async function printConfigAndReturnRelayAddress(): Promise<Address> {
const cfg = await ta.gasless.gaslessConfig();
const cfg = await tonApiClient.gaslessConfig().catch((error: unknown) => {
console.error('Error getting gasless config:',
error instanceof Error ? error.message : String(error));
process.exit(1);
});

console.log('Available jettons for gasless transfer');
console.log(cfg.gasJettons.map(gasJetton => gasJetton.masterId));
console.log(cfg.gasJettons.map((gasJetton: any) => gasJetton.masterId));

console.log(`Relay address to send fees to: ${cfg.relayAddress}`);
return cfg.relayAddress;
Expand Down
15 changes: 9 additions & 6 deletions examples/send-jetton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import { mnemonicToPrivateKey } from '@ton/crypto';
import { TonApiClient } from '@ton-api/client';
import { ContractAdapter } from '@ton-api/ton-adapter';

// Initialize TonApi client
const ta = new TonApiClient({
// Create TonApiClient instance
const tonApiClient = new TonApiClient({
baseUrl: 'https://tonapi.io',
apiKey: 'YOUR_API_KEY', // Optional, improves request limits and access
// apiKey: 'YOUR_API_KEY', // Optional, improves request limits and access
});

// Create an adapter for interacting with contracts
const adapter = new ContractAdapter(ta);
const adapter = new ContractAdapter(tonApiClient);

// Base gas fee required for the jetton transfer
const BASE_JETTON_SEND_AMOUNT = toNano(0.05);
Expand All @@ -32,11 +32,14 @@ const wallet = WalletContractV5R1.create({ workchain: 0, publicKey: keyPair.publ
const contract = adapter.open(wallet); // Open the wallet contract using the adapter

// Get the sender's jetton wallet address from the jetton master contract
const jettonWalletAddressResult = await ta.blockchain.execGetMethodForBlockchainAccount(
const jettonWalletAddressResult = await tonApiClient.execGetMethodForBlockchainAccount(
jettonMaster,
'get_wallet_address',
{ args: [wallet.address.toRawString()] }
);
).catch((error) => {
console.error('Error getting jetton wallet address:', error.message);
process.exit(1);
});

const jettonWallet = Address.parse(jettonWalletAddressResult.decoded.jetton_wallet_address); // Extract the jetton wallet address

Expand Down
8 changes: 4 additions & 4 deletions examples/send-ton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { mnemonicToPrivateKey } from '@ton/crypto';
import { TonApiClient } from '@ton-api/client';
import { ContractAdapter } from '@ton-api/ton-adapter';

// Initialize TonApi client
const ta = new TonApiClient({
// Create TonApiClient instance
const tonApiClient = new TonApiClient({
baseUrl: 'https://tonapi.io',
apiKey: 'YOUR_API_KEY', // Optional, improves limits and access
// apiKey: 'YOUR_API_KEY', // Optional, improves limits and access
});

// Create an adapter for interacting with contracts
const adapter = new ContractAdapter(ta);
const adapter = new ContractAdapter(tonApiClient);

// Convert mnemonic phrase to a private key
const mnemonics = 'word1 word2 ...'.split(' '); // Replace with your mnemonic phrase
Expand Down
25 changes: 16 additions & 9 deletions examples/track-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ function normalizeHash(message: Message, normalizeExternal: boolean): Buffer {
// 1) Using normalizeHash with a manually-created external message
// ----------------------------------------------------------

// Step 1: Initialize the TonAPI client
const ta = new TonApiClient({
// Step 1: Create TonApiClient instance
const tonApiClient = new TonApiClient({
baseUrl: 'https://tonapi.io'
// apiKey: 'YOUR_API_KEY', // Optional, improves request limits and access
});
const adapter = new ContractAdapter(ta);
const adapter = new ContractAdapter(tonApiClient);

// Step 2: Define the wallet and recipient addresses
const destination = Address.parse('EQCKWpx7cNMpvmcN5ObM5lLUZHZRFKqYA4xmw9jOry0ZsF9M');
Expand Down Expand Up @@ -83,9 +83,13 @@ console.log('Manual Message Hash:', manualExtMessageHash.toString('hex'));
await delay(10000);

// Step 8: Retrieve the resulting transaction using the normalized external hash
const manualTransaction = await ta.blockchain.getBlockchainTransactionByMessageHash(
manualExtMessageHash.toString('hex')
);
// You can retry this step if the transaction is not found, until
const manualTransaction = await tonApiClient
.getBlockchainTransactionByMessageHash(manualExtMessageHash.toString('hex'))
.catch((error) => {
console.error('Error fetching transaction:', error.message);
return null;
});
console.log('Manual Transaction Details:', manualTransaction);

// ----------------------------------------------------------
Expand All @@ -106,7 +110,10 @@ const bocExtMessageHash = normalizeHash(bocMessage, true);
console.log('BOC Message Hash:', bocExtMessageHash.toString('hex'));

// Step 3: Retrieve the transaction using that hash
const bocTransaction = await ta.blockchain.getBlockchainTransactionByMessageHash(
bocExtMessageHash.toString('hex')
);
const bocTransaction = await tonApiClient
.getBlockchainTransactionByMessageHash(bocExtMessageHash.toString('hex'))
.catch((error) => {
console.error('Error fetching transaction:', error.message);
return null;
});
console.log('BOC Transaction Details:', bocTransaction);
Loading