Skip to content

Commit

Permalink
Merge pull request #22 from thekiba/feat/reopenable-contract-provider
Browse files Browse the repository at this point in the history
Feat/reopenable contract provider
  • Loading branch information
Dan Volkov authored Feb 23, 2024
2 parents 110beed + a847874 commit 5407afb
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 24 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
},
"devDependencies": {
"@release-it/keep-a-changelog": "^3.1.0",
"@ton/core": "^0.53.0",
"@ton/core": "^0.55.0",
"@ton/crypto": "3.2.0",
"@ton/emulator": "^2.1.1",
"@types/jest": "^27.0.1",
Expand Down
41 changes: 33 additions & 8 deletions src/client/TonClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,26 @@

import { HttpApi } from "./api/HttpApi";
import { AxiosAdapter } from 'axios';
import { Address, beginCell, Cell, comment, Contract, ContractProvider, ContractState, external, loadTransaction, Message, openContract, storeMessage, toNano, Transaction, TupleItem, TupleReader } from '@ton/core';
import {
Address,
beginCell,
Cell,
comment,
Contract,
ContractProvider,
ContractState,
external,
loadTransaction,
Message,
openContract,
storeMessage,
toNano,
Transaction,
TupleItem,
TupleReader,
StateInit,
OpenedContract
} from '@ton/core';
import { Maybe } from "../utils/maybe";

export type TonClientParameters = {
Expand Down Expand Up @@ -257,7 +276,7 @@ export class TonClient {
} else {
const message = external({
to: contract.address,
init: { code: contract.init.code, data: contract.init.data },
init: contract.init,
body: src
});
await this.sendMessage(message);
Expand Down Expand Up @@ -314,8 +333,8 @@ export class TonClient {
* @param init optional init
* @returns provider
*/
provider(address: Address, init: { code: Cell | null, data: Cell | null } | null) {
return createProvider(this, address, init);
provider(address: Address, init?: StateInit | null) {
return createProvider(this, address, init ?? null);
}
}

Expand Down Expand Up @@ -372,7 +391,7 @@ function parseStack(src: any[]) {
return new TupleReader(stack);
}

function createProvider(client: TonClient, address: Address, init: { code: Cell | null, data: Cell | null } | null): ContractProvider {
function createProvider(client: TonClient, address: Address, init: StateInit | null): ContractProvider {
return {
async getState(): Promise<ContractState> {
let state = await client.getContractState(address);
Expand Down Expand Up @@ -422,7 +441,7 @@ function createProvider(client: TonClient, address: Address, init: { code: Cell
// Resolve init
//

let neededInit: { code: Cell | null, data: Cell | null } | null = null;
let neededInit: StateInit | null = null;
if (init && !await client.isContractDeployed(address)) {
neededInit = init;
}
Expand All @@ -433,7 +452,7 @@ function createProvider(client: TonClient, address: Address, init: { code: Cell

const ext = external({
to: address,
init: neededInit ? { code: neededInit.code, data: neededInit.data } : null,
init: neededInit,
body: message
})
let boc = beginCell()
Expand All @@ -445,7 +464,7 @@ function createProvider(client: TonClient, address: Address, init: { code: Cell
async internal(via, message) {

// Resolve init
let neededInit: { code: Cell | null, data: Cell | null } | null = null;
let neededInit: StateInit | null = null;
if (init && (!await client.isContractDeployed(address))) {
neededInit = init;
}
Expand Down Expand Up @@ -481,6 +500,12 @@ function createProvider(client: TonClient, address: Address, init: { code: Cell
init: neededInit,
body
});
},
open<T extends Contract>(contract: T): OpenedContract<T> {
return openContract<T>(contract, (args) => createProvider(client, args.address, args.init ?? null));
},
getTransactions(address: Address, lt: bigint, hash: Buffer, limit?: number): Promise<Transaction[]> {
return client.getTransactions(address, { limit: limit ?? 100, lt: lt.toString(), hash: hash.toString('base64'), inclusive: true });
}
}
}
64 changes: 54 additions & 10 deletions src/client/TonClient4.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import axios, { AxiosAdapter } from "axios";
import { Address, beginCell, Cell, comment, Contract, ContractProvider, ContractState, external, loadTransaction, openContract, parseTuple, serializeTuple, StateInit, storeMessage, toNano, Transaction, TupleItem, TupleReader } from "@ton/core";
import { Address, beginCell, Cell, comment, Contract, ContractProvider, ContractState, external, loadTransaction, openContract, OpenedContract, parseTuple, serializeTuple, StateInit, storeMessage, toNano, Transaction, TupleItem, TupleReader } from "@ton/core";
import { Maybe } from "../utils/maybe";
import { toUrlSafe } from "../utils/toUrlSafe";
import { z } from 'zod';
Expand Down Expand Up @@ -293,8 +293,8 @@ export class TonClient4 {
* @param init optional init data
* @returns provider
*/
provider(address: Address, init?: { code: Cell, data: Cell } | null) {
return createProvider(this, null, address, init ? init : null);
provider(address: Address, init?: StateInit | null) {
return createProvider(this, null, address, init ?? null);
}

/**
Expand All @@ -304,12 +304,12 @@ export class TonClient4 {
* @param init optional init data
* @returns provider
*/
providerAt(block: number, address: Address, init?: { code: Cell, data: Cell } | null) {
return createProvider(this, block, address, init ? init : null);
providerAt(block: number, address: Address, init?: StateInit | null) {
return createProvider(this, block, address, init ?? null);
}
}

function createProvider(client: TonClient4, block: number | null, address: Address, init: { code: Cell, data: Cell } | null): ContractProvider {
function createProvider(client: TonClient4, block: number | null, address: Address, init: StateInit | null): ContractProvider {
return {
async getState(): Promise<ContractState> {

Expand Down Expand Up @@ -380,15 +380,15 @@ function createProvider(client: TonClient4, block: number | null, address: Addre
let last = await client.getLastBlock();

// Resolve init
let neededInit: { code: Cell | null, data: Cell | null } | null = null;
let neededInit: StateInit | null = null;
if (init && (await client.getAccountLite(last.last.seqno, address)).account.state.type !== 'active') {
neededInit = init;
}

// Send with state init
const ext = external({
to: address,
init: neededInit ? { code: neededInit.code, data: neededInit.data } : null,
init: neededInit,
body: message
});
let pkg = beginCell()
Expand All @@ -403,7 +403,7 @@ function createProvider(client: TonClient4, block: number | null, address: Addre
let last = await client.getLastBlock();

// Resolve init
let neededInit: { code: Cell | null, data: Cell | null } | null = null;
let neededInit: StateInit | null = null;
if (init && (await client.getAccountLite(last.last.seqno, address)).account.state.type !== 'active') {
neededInit = init;
}
Expand Down Expand Up @@ -439,6 +439,50 @@ function createProvider(client: TonClient4, block: number | null, address: Addre
init: neededInit,
body
});
},
open<T extends Contract>(contract: T): OpenedContract<T> {
return openContract<T>(contract, (args) => createProvider(client, block, args.address, args.init ?? null));
},
async getTransactions(address: Address, lt: bigint, hash: Buffer, limit?: number): Promise<Transaction[]> {
// Resolve last
const useLimit = typeof limit === 'number';
if (useLimit && limit <= 0) {
return [];
}

// Load transactions
let transactions: Transaction[] = [];
do {
const txs = await client.getAccountTransactions(address, lt, hash);

const firstTx = txs[0].tx;
const [firstLt, firstHash] = [firstTx.lt, firstTx.hash()];
const needSkipFirst = transactions.length > 0 && firstLt === lt && firstHash.equals(hash);
if (needSkipFirst) {
txs.shift();
}

if (txs.length === 0) {
break;
}
const lastTx = txs[txs.length - 1].tx;
const [lastLt, lastHash] = [lastTx.lt, lastTx.hash()];
if (lastLt === lt && lastHash.equals(hash)) {
break;
}

transactions.push(...txs.map(tx => tx.tx));
lt = lastLt;
hash = lastHash;
} while (useLimit && transactions.length < limit);

// Apply limit
if (useLimit) {
transactions = transactions.slice(0, limit);
}

// Return transactions
return transactions;
}
}
}
Expand Down Expand Up @@ -724,4 +768,4 @@ export type ParsedTransaction = z.infer<typeof parsedTransactionCodec>;
export type ParsedTransactions = {
blocks: z.infer<typeof blocksCodec>,
transactions: ParsedTransaction[]
};
};
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -950,14 +950,14 @@ __metadata:
languageName: node
linkType: hard

"@ton/core@npm:^0.53.0":
version: 0.53.0
resolution: "@ton/core@npm:0.53.0"
"@ton/core@npm:^0.55.0":
version: 0.55.0
resolution: "@ton/core@npm:0.55.0"
dependencies:
symbol.inspect: 1.0.1
peerDependencies:
"@ton/crypto": ">=3.2.0"
checksum: 6d84040bce46b8167d106ca07183c60a935b3be1934a8049f8296c7a957a7d9ae8f1f1d885df2c388c801813cfa5ac742190dfabd2b34529c338754160040d44
checksum: 62201f0358cb9f5b1014f85681589008c9db193dd97294d48d22b590d468c33574371f4d8b203406fe8b1721d437930eb1b896c357a997fed29fd222e7da2681
languageName: node
linkType: hard

Expand Down Expand Up @@ -1000,7 +1000,7 @@ __metadata:
resolution: "@ton/ton@workspace:."
dependencies:
"@release-it/keep-a-changelog": ^3.1.0
"@ton/core": ^0.53.0
"@ton/core": ^0.55.0
"@ton/crypto": 3.2.0
"@ton/emulator": ^2.1.1
"@types/jest": ^27.0.1
Expand Down

0 comments on commit 5407afb

Please sign in to comment.