@tonappchain/sdk 0.6.5-mainnet-alpha → 0.7.0-rc7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/contractOpener.d.ts +1 -1
- package/dist/adapters/contractOpener.js +7 -8
- package/dist/adapters/retryableContractOpener.d.ts +21 -0
- package/dist/adapters/retryableContractOpener.js +101 -0
- package/dist/assets/AssetCache.d.ts +23 -0
- package/dist/assets/AssetCache.js +36 -0
- package/dist/assets/AssetFactory.d.ts +19 -0
- package/dist/assets/AssetFactory.js +45 -0
- package/dist/assets/FT.d.ts +55 -0
- package/dist/assets/FT.js +206 -0
- package/dist/assets/NFT.d.ts +69 -0
- package/dist/assets/NFT.js +200 -0
- package/dist/assets/TON.d.ts +38 -0
- package/dist/assets/TON.js +91 -0
- package/dist/assets/index.d.ts +4 -0
- package/dist/assets/index.js +11 -0
- package/dist/errors/errors.d.ts +6 -0
- package/dist/errors/errors.js +15 -1
- package/dist/errors/index.d.ts +2 -2
- package/dist/errors/index.js +26 -21
- package/dist/errors/instances.d.ts +9 -4
- package/dist/errors/instances.js +19 -5
- package/dist/index.d.ts +12 -6
- package/dist/index.js +24 -13
- package/dist/sdk/Configuration.d.ts +21 -0
- package/dist/sdk/Configuration.js +90 -0
- package/dist/sdk/LiteSequencerClient.d.ts +1 -1
- package/dist/sdk/LiteSequencerClient.js +5 -11
- package/dist/sdk/Logger.d.ts +13 -0
- package/dist/sdk/Logger.js +25 -0
- package/dist/sdk/OperationTracker.d.ts +21 -6
- package/dist/sdk/OperationTracker.js +155 -75
- package/dist/sdk/Simulator.d.ts +23 -0
- package/dist/sdk/Simulator.js +169 -0
- package/dist/sdk/StartTracking.d.ts +6 -0
- package/dist/sdk/StartTracking.js +66 -29
- package/dist/sdk/TacSdk.d.ts +12 -41
- package/dist/sdk/TacSdk.js +69 -712
- package/dist/sdk/TransactionManager.d.ts +22 -0
- package/dist/sdk/TransactionManager.js +264 -0
- package/dist/sdk/TxFinalizer.d.ts +10 -0
- package/dist/sdk/TxFinalizer.js +104 -0
- package/dist/sdk/Utils.d.ts +12 -4
- package/dist/sdk/Utils.js +80 -16
- package/dist/sdk/Validator.d.ts +9 -0
- package/dist/sdk/Validator.js +43 -0
- package/dist/sender/BatchSender.d.ts +7 -4
- package/dist/sender/BatchSender.js +18 -6
- package/dist/sender/RawSender.d.ts +9 -4
- package/dist/sender/RawSender.js +46 -18
- package/dist/sender/SenderAbstraction.d.ts +5 -3
- package/dist/sender/SenderFactory.d.ts +1 -1
- package/dist/sender/SenderFactory.js +5 -4
- package/dist/sender/TonConnectSender.d.ts +5 -3
- package/dist/sender/TonConnectSender.js +12 -8
- package/dist/sender/index.d.ts +1 -1
- package/dist/sender/index.js +1 -1
- package/dist/structs/InternalStruct.d.ts +36 -33
- package/dist/structs/Services.d.ts +40 -0
- package/dist/structs/Services.js +2 -0
- package/dist/structs/Struct.d.ts +100 -79
- package/dist/structs/Struct.js +11 -1
- package/dist/wrappers/HighloadQueryId.js +0 -1
- package/dist/wrappers/HighloadWalletV3.d.ts +3 -2
- package/dist/wrappers/HighloadWalletV3.js +5 -2
- package/dist/wrappers/JettonWallet.d.ts +11 -2
- package/dist/wrappers/JettonWallet.js +33 -16
- package/package.json +2 -2
|
@@ -4,16 +4,16 @@ exports.liteClientOpener = liteClientOpener;
|
|
|
4
4
|
exports.sandboxOpener = sandboxOpener;
|
|
5
5
|
exports.orbsOpener = orbsOpener;
|
|
6
6
|
exports.orbsOpener4 = orbsOpener4;
|
|
7
|
-
const ton_lite_client_1 = require("@tonappchain/ton-lite-client");
|
|
8
|
-
const Struct_1 = require("../structs/Struct");
|
|
9
7
|
const ton_access_1 = require("@orbs-network/ton-access");
|
|
10
8
|
const ton_1 = require("@ton/ton");
|
|
11
9
|
const artifacts_1 = require("@tonappchain/artifacts");
|
|
10
|
+
const ton_lite_client_1 = require("@tonappchain/ton-lite-client");
|
|
11
|
+
const Struct_1 = require("../structs/Struct");
|
|
12
12
|
function intToIP(int) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
const part1 = int & 255;
|
|
14
|
+
const part2 = (int >> 8) & 255;
|
|
15
|
+
const part3 = (int >> 16) & 255;
|
|
16
|
+
const part4 = (int >> 24) & 255;
|
|
17
17
|
return part4 + '.' + part3 + '.' + part2 + '.' + part1;
|
|
18
18
|
}
|
|
19
19
|
async function getDefaultLiteServers(network) {
|
|
@@ -70,8 +70,7 @@ async function orbsOpener(network) {
|
|
|
70
70
|
const endpoint = await (0, ton_access_1.getHttpEndpoint)({
|
|
71
71
|
network,
|
|
72
72
|
});
|
|
73
|
-
|
|
74
|
-
return client;
|
|
73
|
+
return new ton_1.TonClient({ endpoint });
|
|
75
74
|
}
|
|
76
75
|
async function orbsOpener4(network, timeout = 10000) {
|
|
77
76
|
const endpoint = await (0, ton_access_1.getHttpV4Endpoint)({ network });
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { SandboxContract } from '@ton/sandbox';
|
|
2
|
+
import { Address, Contract, OpenedContract } from '@ton/ton';
|
|
3
|
+
import { mainnet, testnet } from '@tonappchain/artifacts';
|
|
4
|
+
import { ContractOpener, ContractState } from '../structs/Struct';
|
|
5
|
+
export interface OpenerConfig {
|
|
6
|
+
opener: ContractOpener;
|
|
7
|
+
retries: number;
|
|
8
|
+
retryDelay: number;
|
|
9
|
+
}
|
|
10
|
+
export declare class RetryableContractOpener implements ContractOpener {
|
|
11
|
+
private readonly openerConfigs;
|
|
12
|
+
constructor(openerConfigs: OpenerConfig[]);
|
|
13
|
+
open<T extends Contract>(src: T): OpenedContract<T> | SandboxContract<T>;
|
|
14
|
+
getContractState(address: Address): Promise<ContractState>;
|
|
15
|
+
closeConnections(): void;
|
|
16
|
+
private executeWithFallback;
|
|
17
|
+
private tryWithRetries;
|
|
18
|
+
private createRetryableContract;
|
|
19
|
+
private callMethodAcrossOpeners;
|
|
20
|
+
}
|
|
21
|
+
export declare function createDefaultRetryableOpener(artifacts: typeof testnet | typeof mainnet, maxRetries?: number, retryDelay?: number): Promise<ContractOpener>;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RetryableContractOpener = void 0;
|
|
4
|
+
exports.createDefaultRetryableOpener = createDefaultRetryableOpener;
|
|
5
|
+
const ton_1 = require("@ton/ton");
|
|
6
|
+
const artifacts_1 = require("@tonappchain/artifacts");
|
|
7
|
+
const instances_1 = require("../errors/instances");
|
|
8
|
+
const Struct_1 = require("../structs/Struct");
|
|
9
|
+
const contractOpener_1 = require("./contractOpener");
|
|
10
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
11
|
+
class RetryableContractOpener {
|
|
12
|
+
constructor(openerConfigs) {
|
|
13
|
+
if (openerConfigs.length === 0) {
|
|
14
|
+
throw new Error('No ContractOpener instances available');
|
|
15
|
+
}
|
|
16
|
+
this.openerConfigs = openerConfigs;
|
|
17
|
+
}
|
|
18
|
+
open(src) {
|
|
19
|
+
const firstConfig = this.openerConfigs[0];
|
|
20
|
+
const contract = firstConfig.opener.open(src);
|
|
21
|
+
return this.createRetryableContract(contract, src);
|
|
22
|
+
}
|
|
23
|
+
async getContractState(address) {
|
|
24
|
+
const result = await this.executeWithFallback((config) => config.opener.getContractState(address));
|
|
25
|
+
if (result.success && result.data) {
|
|
26
|
+
return result.data;
|
|
27
|
+
}
|
|
28
|
+
throw result.lastError || (0, instances_1.allContractOpenerFailedError)('Failed to get contract state');
|
|
29
|
+
}
|
|
30
|
+
closeConnections() {
|
|
31
|
+
for (const config of this.openerConfigs) {
|
|
32
|
+
config.opener.closeConnections?.();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async executeWithFallback(operation) {
|
|
36
|
+
let lastError;
|
|
37
|
+
for (const config of this.openerConfigs) {
|
|
38
|
+
const result = await this.tryWithRetries(() => operation(config), config);
|
|
39
|
+
if (result.success) {
|
|
40
|
+
return { success: true, data: result.data };
|
|
41
|
+
}
|
|
42
|
+
lastError = result.lastError;
|
|
43
|
+
}
|
|
44
|
+
return { success: false, lastError };
|
|
45
|
+
}
|
|
46
|
+
async tryWithRetries(operation, config) {
|
|
47
|
+
let lastError;
|
|
48
|
+
for (let attempt = 0; attempt <= config.retries; attempt++) {
|
|
49
|
+
try {
|
|
50
|
+
const data = await operation();
|
|
51
|
+
return { success: true, data };
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
lastError = error;
|
|
55
|
+
if (attempt < config.retries) {
|
|
56
|
+
await sleep(config.retryDelay);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { success: false, lastError };
|
|
61
|
+
}
|
|
62
|
+
createRetryableContract(contract, src) {
|
|
63
|
+
return new Proxy(contract, {
|
|
64
|
+
get: (target, prop) => {
|
|
65
|
+
const value = Reflect.get(target, prop);
|
|
66
|
+
if (typeof value !== 'function')
|
|
67
|
+
return value;
|
|
68
|
+
return async (...args) => {
|
|
69
|
+
return this.callMethodAcrossOpeners(prop, args, src);
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async callMethodAcrossOpeners(methodName, args, src) {
|
|
75
|
+
const result = await this.executeWithFallback((config) => {
|
|
76
|
+
const contract = config.opener.open(src);
|
|
77
|
+
const method = Reflect.get(contract, methodName);
|
|
78
|
+
if (typeof method !== 'function') {
|
|
79
|
+
throw new Error(`Method ${String(methodName)} is not a function`);
|
|
80
|
+
}
|
|
81
|
+
return method.call(contract, ...args);
|
|
82
|
+
});
|
|
83
|
+
if (result.success)
|
|
84
|
+
return result.data;
|
|
85
|
+
throw result.lastError || (0, instances_1.allContractOpenerFailedError)('failed to call method in contract');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.RetryableContractOpener = RetryableContractOpener;
|
|
89
|
+
async function createDefaultRetryableOpener(artifacts, maxRetries = 3, retryDelay = 1000) {
|
|
90
|
+
const tonClient = new ton_1.TonClient({
|
|
91
|
+
endpoint: new URL('api/v2/jsonRPC', artifacts.TON_RPC_ENDPOINT_BY_TAC).toString(),
|
|
92
|
+
});
|
|
93
|
+
const network = artifacts === artifacts_1.testnet ? Struct_1.Network.TESTNET : Struct_1.Network.MAINNET;
|
|
94
|
+
const opener4 = await (0, contractOpener_1.orbsOpener4)(network);
|
|
95
|
+
const opener = await (0, contractOpener_1.orbsOpener)(network);
|
|
96
|
+
return new RetryableContractOpener([
|
|
97
|
+
{ opener: tonClient, retries: maxRetries, retryDelay },
|
|
98
|
+
{ opener: opener4, retries: maxRetries, retryDelay },
|
|
99
|
+
{ opener: opener, retries: maxRetries, retryDelay },
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Asset } from '../structs/Struct';
|
|
2
|
+
export declare class AssetCache {
|
|
3
|
+
private static readonly cache;
|
|
4
|
+
/**
|
|
5
|
+
* Get asset from cache
|
|
6
|
+
*/
|
|
7
|
+
static get(token: {
|
|
8
|
+
address: string;
|
|
9
|
+
index?: bigint;
|
|
10
|
+
}): Asset | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Set asset in cache
|
|
13
|
+
*/
|
|
14
|
+
static set(token: {
|
|
15
|
+
address: string;
|
|
16
|
+
index?: bigint;
|
|
17
|
+
}, asset: Asset): void;
|
|
18
|
+
/**
|
|
19
|
+
* Clear the cache
|
|
20
|
+
*/
|
|
21
|
+
static clear(): void;
|
|
22
|
+
private static generateKey;
|
|
23
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AssetCache = void 0;
|
|
4
|
+
class AssetCache {
|
|
5
|
+
/**
|
|
6
|
+
* Get asset from cache
|
|
7
|
+
*/
|
|
8
|
+
static get(token) {
|
|
9
|
+
const key = this.generateKey(token);
|
|
10
|
+
return this.cache.get(key);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Set asset in cache
|
|
14
|
+
*/
|
|
15
|
+
static set(token, asset) {
|
|
16
|
+
const key = this.generateKey(token);
|
|
17
|
+
this.cache.set(key, asset);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Clear the cache
|
|
21
|
+
*/
|
|
22
|
+
static clear() {
|
|
23
|
+
this.cache.clear();
|
|
24
|
+
}
|
|
25
|
+
static generateKey(token) {
|
|
26
|
+
// Normalize address to lowercase for consistency
|
|
27
|
+
const normalizedAddress = token.address.toLowerCase();
|
|
28
|
+
const parts = [normalizedAddress];
|
|
29
|
+
if (token.index !== undefined) {
|
|
30
|
+
parts.push(token.index.toString());
|
|
31
|
+
}
|
|
32
|
+
return parts.join('|');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.AssetCache = AssetCache;
|
|
36
|
+
AssetCache.cache = new Map();
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { IConfiguration } from '../structs/Services';
|
|
2
|
+
import { Asset, AssetType, EVMAddress, NFTAddressType, TVMAddress } from '../structs/Struct';
|
|
3
|
+
export declare class AssetFactory {
|
|
4
|
+
static from(configuration: IConfiguration, token: {
|
|
5
|
+
address: TVMAddress | EVMAddress;
|
|
6
|
+
tokenType: AssetType.FT;
|
|
7
|
+
} | {
|
|
8
|
+
address: TVMAddress | EVMAddress;
|
|
9
|
+
tokenType: AssetType.NFT;
|
|
10
|
+
addressType: NFTAddressType.COLLECTION;
|
|
11
|
+
index: bigint;
|
|
12
|
+
} | {
|
|
13
|
+
address: TVMAddress;
|
|
14
|
+
tokenType: AssetType.NFT;
|
|
15
|
+
addressType: NFTAddressType.ITEM;
|
|
16
|
+
}): Promise<Asset>;
|
|
17
|
+
private static createFTAsset;
|
|
18
|
+
private static createNFTAsset;
|
|
19
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AssetFactory = void 0;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
const Struct_1 = require("../structs/Struct");
|
|
6
|
+
const AssetCache_1 = require("./AssetCache");
|
|
7
|
+
const FT_1 = require("./FT");
|
|
8
|
+
const NFT_1 = require("./NFT");
|
|
9
|
+
const TON_1 = require("./TON");
|
|
10
|
+
class AssetFactory {
|
|
11
|
+
/// PUBLIC
|
|
12
|
+
static async from(configuration, token) {
|
|
13
|
+
if (token.address === '' || token.address === configuration.nativeTONAddress) {
|
|
14
|
+
return TON_1.TON.create(configuration);
|
|
15
|
+
}
|
|
16
|
+
const cachedAsset = AssetCache_1.AssetCache.get(token);
|
|
17
|
+
if (cachedAsset) {
|
|
18
|
+
return cachedAsset.clone.withAmount({ rawAmount: 0n });
|
|
19
|
+
}
|
|
20
|
+
const asset = token.tokenType === Struct_1.AssetType.FT
|
|
21
|
+
? await this.createFTAsset(configuration, token.address)
|
|
22
|
+
: await this.createNFTAsset(configuration, token.address, token.addressType, token.addressType === Struct_1.NFTAddressType.COLLECTION ? token.index : undefined);
|
|
23
|
+
AssetCache_1.AssetCache.set(token, asset);
|
|
24
|
+
return asset;
|
|
25
|
+
}
|
|
26
|
+
/// PRIVATE
|
|
27
|
+
/// CREATE FT ASSET
|
|
28
|
+
static async createFTAsset(configuration, address) {
|
|
29
|
+
return FT_1.FT.fromAddress(configuration, address);
|
|
30
|
+
}
|
|
31
|
+
/// CREATE NFT ASSET
|
|
32
|
+
static async createNFTAsset(configuration, address, addressType, index) {
|
|
33
|
+
if (addressType === Struct_1.NFTAddressType.ITEM) {
|
|
34
|
+
return NFT_1.NFT.fromItem(configuration, address);
|
|
35
|
+
}
|
|
36
|
+
if (addressType === Struct_1.NFTAddressType.COLLECTION) {
|
|
37
|
+
if (!index) {
|
|
38
|
+
throw (0, errors_1.indexRequiredError)(address);
|
|
39
|
+
}
|
|
40
|
+
return NFT_1.NFT.fromCollection(configuration, { collection: address, index });
|
|
41
|
+
}
|
|
42
|
+
throw (0, errors_1.unknownTokenTypeError)(address, 'NFT address type is unknown: should be either ITEM or COLLECTION');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.AssetFactory = AssetFactory;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { SandboxContract } from '@ton/sandbox';
|
|
2
|
+
import { Cell, OpenedContract } from '@ton/ton';
|
|
3
|
+
import { AssetOpType } from '../structs/InternalStruct';
|
|
4
|
+
import { IConfiguration } from '../structs/Services';
|
|
5
|
+
import { AssetType, ContractOpener, EVMAddress, FeeParams, TVMAddress, UserWalletBalanceExtended } from '../structs/Struct';
|
|
6
|
+
import { Asset, Origin } from '../structs/Struct';
|
|
7
|
+
import { JettonWallet } from '../wrappers/JettonWallet';
|
|
8
|
+
export declare class FT implements Asset {
|
|
9
|
+
private _tokenAddress;
|
|
10
|
+
readonly type: AssetType;
|
|
11
|
+
readonly origin: Origin;
|
|
12
|
+
private _configuration;
|
|
13
|
+
private _jettonMinter;
|
|
14
|
+
private _decimals?;
|
|
15
|
+
private _transferAmount;
|
|
16
|
+
private _evmAddress?;
|
|
17
|
+
get address(): string;
|
|
18
|
+
static getJettonData(contractOpener: ContractOpener, address: TVMAddress): Promise<import("../wrappers/JettonMaster").JettonMasterData>;
|
|
19
|
+
static getOrigin(configuration: IConfiguration, address: TVMAddress): Promise<Origin>;
|
|
20
|
+
static getTVMAddress(configuration: IConfiguration, address: EVMAddress): Promise<string>;
|
|
21
|
+
private constructor();
|
|
22
|
+
static fromAddress(configuration: IConfiguration, address: TVMAddress | EVMAddress): Promise<FT>;
|
|
23
|
+
get rawAmount(): bigint;
|
|
24
|
+
get clone(): FT;
|
|
25
|
+
withAmount(amount: {
|
|
26
|
+
rawAmount: bigint;
|
|
27
|
+
} | {
|
|
28
|
+
amount: number;
|
|
29
|
+
}): Promise<FT>;
|
|
30
|
+
addAmount(amount: {
|
|
31
|
+
rawAmount: bigint;
|
|
32
|
+
} | {
|
|
33
|
+
amount: number;
|
|
34
|
+
}): Promise<FT>;
|
|
35
|
+
getDecimals(): Promise<number>;
|
|
36
|
+
getEVMAddress(): Promise<string>;
|
|
37
|
+
getTVMAddress(): Promise<string>;
|
|
38
|
+
generatePayload(params: {
|
|
39
|
+
excessReceiver: string;
|
|
40
|
+
evmData: Cell;
|
|
41
|
+
crossChainTonAmount?: bigint;
|
|
42
|
+
forwardFeeTonAmount?: bigint;
|
|
43
|
+
feeParams?: FeeParams;
|
|
44
|
+
}): Promise<Cell>;
|
|
45
|
+
get opType(): AssetOpType.JETTON_BURN | AssetOpType.JETTON_TRANSFER;
|
|
46
|
+
getWallet(userAddress: string): Promise<OpenedContract<JettonWallet> | SandboxContract<JettonWallet>>;
|
|
47
|
+
getUserWalletAddress(userAddress: string): Promise<string>;
|
|
48
|
+
getUserBalance(userAddress: string): Promise<bigint>;
|
|
49
|
+
getUserBalanceExtended(userAddress: string): Promise<UserWalletBalanceExtended>;
|
|
50
|
+
checkBalance(userAddress: string): Promise<void>;
|
|
51
|
+
checkCanBeTransferedBy(userAddress: string): Promise<void>;
|
|
52
|
+
getBalanceOf(userAddress: string): Promise<bigint>;
|
|
53
|
+
private getTransferPayload;
|
|
54
|
+
private getBurnPayload;
|
|
55
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FT = void 0;
|
|
4
|
+
const ton_1 = require("@ton/ton");
|
|
5
|
+
const ethers_1 = require("ethers");
|
|
6
|
+
const errors_1 = require("../errors");
|
|
7
|
+
const Consts_1 = require("../sdk/Consts");
|
|
8
|
+
const Utils_1 = require("../sdk/Utils");
|
|
9
|
+
const Validator_1 = require("../sdk/Validator");
|
|
10
|
+
const InternalStruct_1 = require("../structs/InternalStruct");
|
|
11
|
+
const Struct_1 = require("../structs/Struct");
|
|
12
|
+
const Struct_2 = require("../structs/Struct");
|
|
13
|
+
const JettonMaster_1 = require("../wrappers/JettonMaster");
|
|
14
|
+
const JettonWallet_1 = require("../wrappers/JettonWallet");
|
|
15
|
+
class FT {
|
|
16
|
+
get address() {
|
|
17
|
+
return this._tokenAddress.toString();
|
|
18
|
+
}
|
|
19
|
+
static async getJettonData(contractOpener, address) {
|
|
20
|
+
Validator_1.Validator.validateTVMAddress(address);
|
|
21
|
+
const jetton = contractOpener.open(JettonMaster_1.JettonMaster.createFromAddress(ton_1.Address.parse(address)));
|
|
22
|
+
return await jetton.getJettonData();
|
|
23
|
+
}
|
|
24
|
+
static async getOrigin(configuration, address) {
|
|
25
|
+
const { jettonMinterCode, crossChainLayerAddress, jettonWalletCode } = configuration.TONParams;
|
|
26
|
+
const { code: thisCodeBOC } = await configuration.TONParams.contractOpener.getContractState(ton_1.Address.parse(address));
|
|
27
|
+
if (!thisCodeBOC) {
|
|
28
|
+
throw errors_1.emptyContractError;
|
|
29
|
+
}
|
|
30
|
+
const thisCode = ton_1.Cell.fromBoc(thisCodeBOC)[0];
|
|
31
|
+
if (!jettonMinterCode.equals(thisCode)) {
|
|
32
|
+
return Struct_2.Origin.TON;
|
|
33
|
+
}
|
|
34
|
+
const jettonMinter = configuration.TONParams.contractOpener.open(JettonMaster_1.JettonMaster.createFromAddress(ton_1.Address.parse(address)));
|
|
35
|
+
const evmAddress = await jettonMinter.getEVMAddress();
|
|
36
|
+
const expectedMinterAddress = await (0, Utils_1.calculateContractAddress)(jettonMinterCode, (0, ton_1.beginCell)()
|
|
37
|
+
.storeCoins(0)
|
|
38
|
+
.storeAddress(ton_1.Address.parse(crossChainLayerAddress))
|
|
39
|
+
.storeAddress(null)
|
|
40
|
+
.storeRef((0, ton_1.beginCell)().endCell())
|
|
41
|
+
.storeRef(jettonWalletCode)
|
|
42
|
+
.storeStringTail(evmAddress)
|
|
43
|
+
.endCell());
|
|
44
|
+
if (!expectedMinterAddress.equals(ton_1.Address.parse(address))) {
|
|
45
|
+
return Struct_2.Origin.TON;
|
|
46
|
+
}
|
|
47
|
+
return Struct_2.Origin.TAC;
|
|
48
|
+
}
|
|
49
|
+
static async getTVMAddress(configuration, address) {
|
|
50
|
+
Validator_1.Validator.validateEVMAddress(address);
|
|
51
|
+
const exists = await configuration.TACParams.tokenUtils['exists(address)'](address);
|
|
52
|
+
if (exists) {
|
|
53
|
+
const erc20Token = configuration.artifacts.tac.wrappers.CrossChainLayerERC20FactoryTAC.connect(address, configuration.TACParams.provider);
|
|
54
|
+
const info = await erc20Token.getInfo();
|
|
55
|
+
return info.tvmAddress;
|
|
56
|
+
}
|
|
57
|
+
const jettonMaster = JettonMaster_1.JettonMaster.createFromConfig({
|
|
58
|
+
evmTokenAddress: address,
|
|
59
|
+
crossChainLayerAddress: ton_1.Address.parse(configuration.TONParams.crossChainLayerAddress),
|
|
60
|
+
code: configuration.TONParams.jettonMinterCode,
|
|
61
|
+
walletCode: configuration.TONParams.jettonWalletCode,
|
|
62
|
+
});
|
|
63
|
+
return jettonMaster.address.toString();
|
|
64
|
+
}
|
|
65
|
+
constructor(address, origin, configuration) {
|
|
66
|
+
this.type = Struct_1.AssetType.FT;
|
|
67
|
+
this._tokenAddress = ton_1.Address.parse(address);
|
|
68
|
+
this._configuration = configuration;
|
|
69
|
+
this._jettonMinter = this._configuration.TONParams.contractOpener.open(new JettonMaster_1.JettonMaster(this._tokenAddress));
|
|
70
|
+
this.origin = origin;
|
|
71
|
+
this._transferAmount = 0n;
|
|
72
|
+
}
|
|
73
|
+
static async fromAddress(configuration, address) {
|
|
74
|
+
const tvmAddress = (0, ethers_1.isAddress)(address) ? await this.getTVMAddress(configuration, address) : address;
|
|
75
|
+
const origin = await FT.getOrigin(configuration, tvmAddress).catch((e) => {
|
|
76
|
+
if (e instanceof errors_1.ContractError) {
|
|
77
|
+
return Struct_2.Origin.TAC;
|
|
78
|
+
}
|
|
79
|
+
throw e;
|
|
80
|
+
});
|
|
81
|
+
return new FT(tvmAddress, origin, configuration);
|
|
82
|
+
}
|
|
83
|
+
get rawAmount() {
|
|
84
|
+
return this._transferAmount;
|
|
85
|
+
}
|
|
86
|
+
get clone() {
|
|
87
|
+
const ft = new FT(this._tokenAddress.toString(), this.origin, this._configuration);
|
|
88
|
+
ft._transferAmount = this._transferAmount;
|
|
89
|
+
ft._evmAddress = this._evmAddress;
|
|
90
|
+
ft._decimals = this._decimals;
|
|
91
|
+
return ft;
|
|
92
|
+
}
|
|
93
|
+
async withAmount(amount) {
|
|
94
|
+
if (this._transferAmount > 0n) {
|
|
95
|
+
// clone token if withAmount set before to avoid changing the original token
|
|
96
|
+
const newToken = this.clone;
|
|
97
|
+
newToken._transferAmount =
|
|
98
|
+
'rawAmount' in amount ? amount.rawAmount : (0, Utils_1.calculateRawAmount)(amount.amount, await this.getDecimals());
|
|
99
|
+
return newToken;
|
|
100
|
+
}
|
|
101
|
+
if ('rawAmount' in amount) {
|
|
102
|
+
this._transferAmount = amount.rawAmount;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
const decimals = await this.getDecimals();
|
|
106
|
+
this._transferAmount = (0, Utils_1.calculateRawAmount)(amount.amount, decimals);
|
|
107
|
+
}
|
|
108
|
+
return this;
|
|
109
|
+
}
|
|
110
|
+
async addAmount(amount) {
|
|
111
|
+
if ('rawAmount' in amount) {
|
|
112
|
+
this._transferAmount = this._transferAmount + amount.rawAmount;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
const decimals = await this.getDecimals();
|
|
116
|
+
this._transferAmount = this._transferAmount + (0, Utils_1.calculateRawAmount)(amount.amount, decimals);
|
|
117
|
+
}
|
|
118
|
+
return this;
|
|
119
|
+
}
|
|
120
|
+
async getDecimals() {
|
|
121
|
+
if (!this._decimals) {
|
|
122
|
+
const decimalsRaw = (await this._jettonMinter.getJettonData()).content.metadata.decimals;
|
|
123
|
+
this._decimals = decimalsRaw ? Number(decimalsRaw) : 9;
|
|
124
|
+
}
|
|
125
|
+
return this._decimals;
|
|
126
|
+
}
|
|
127
|
+
async getEVMAddress() {
|
|
128
|
+
if (this._evmAddress) {
|
|
129
|
+
return this._evmAddress;
|
|
130
|
+
}
|
|
131
|
+
if (this.origin === Struct_2.Origin.TAC) {
|
|
132
|
+
this._evmAddress = await this._jettonMinter.getEVMAddress();
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
this._evmAddress = await this._configuration.TACParams.tokenUtils.computeAddress(this._tokenAddress.toString());
|
|
136
|
+
}
|
|
137
|
+
return this._evmAddress;
|
|
138
|
+
}
|
|
139
|
+
async getTVMAddress() {
|
|
140
|
+
return this._tokenAddress.toString();
|
|
141
|
+
}
|
|
142
|
+
async generatePayload(params) {
|
|
143
|
+
const { excessReceiver, evmData, crossChainTonAmount = 0n, forwardFeeTonAmount = 0n, feeParams } = params;
|
|
144
|
+
const feeData = (0, Utils_1.generateFeeData)(feeParams);
|
|
145
|
+
let payload;
|
|
146
|
+
switch (this.opType) {
|
|
147
|
+
case InternalStruct_1.AssetOpType.JETTON_BURN:
|
|
148
|
+
payload = this.getBurnPayload(this._transferAmount, this._configuration.TONParams.crossChainLayerAddress, evmData, crossChainTonAmount, feeData);
|
|
149
|
+
break;
|
|
150
|
+
case InternalStruct_1.AssetOpType.JETTON_TRANSFER:
|
|
151
|
+
payload = this.getTransferPayload(this._transferAmount, this._configuration.TONParams.jettonProxyAddress, excessReceiver, evmData, crossChainTonAmount, forwardFeeTonAmount, feeData);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
return payload;
|
|
155
|
+
}
|
|
156
|
+
get opType() {
|
|
157
|
+
return this.origin === 'TAC' ? InternalStruct_1.AssetOpType.JETTON_BURN : InternalStruct_1.AssetOpType.JETTON_TRANSFER;
|
|
158
|
+
}
|
|
159
|
+
async getWallet(userAddress) {
|
|
160
|
+
const walletAddress = await this.getUserWalletAddress(userAddress);
|
|
161
|
+
return this._configuration.TONParams.contractOpener.open(JettonWallet_1.JettonWallet.createFromAddress(ton_1.Address.parse(walletAddress)));
|
|
162
|
+
}
|
|
163
|
+
async getUserWalletAddress(userAddress) {
|
|
164
|
+
return this._jettonMinter.getWalletAddress(userAddress);
|
|
165
|
+
}
|
|
166
|
+
async getUserBalance(userAddress) {
|
|
167
|
+
const wallet = await this.getWallet(userAddress);
|
|
168
|
+
return BigInt(await wallet.getJettonBalance());
|
|
169
|
+
}
|
|
170
|
+
async getUserBalanceExtended(userAddress) {
|
|
171
|
+
const masterState = await this._configuration.TONParams.contractOpener.getContractState(this._tokenAddress);
|
|
172
|
+
if (masterState.state !== 'active') {
|
|
173
|
+
return { exists: false };
|
|
174
|
+
}
|
|
175
|
+
const wallet = await this.getWallet(userAddress);
|
|
176
|
+
const rawAmount = await wallet.getJettonBalance();
|
|
177
|
+
const decimals = await this.getDecimals();
|
|
178
|
+
return {
|
|
179
|
+
rawAmount,
|
|
180
|
+
decimals,
|
|
181
|
+
amount: (0, Utils_1.calculateAmount)(rawAmount, decimals),
|
|
182
|
+
exists: true,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
async checkBalance(userAddress) {
|
|
186
|
+
const balance = await this.getUserBalance(userAddress);
|
|
187
|
+
if (balance < this._transferAmount) {
|
|
188
|
+
throw (0, errors_1.insufficientBalanceError)(this._tokenAddress.toString());
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async checkCanBeTransferedBy(userAddress) {
|
|
192
|
+
await this.checkBalance(userAddress);
|
|
193
|
+
}
|
|
194
|
+
async getBalanceOf(userAddress) {
|
|
195
|
+
return this.getUserBalance(userAddress);
|
|
196
|
+
}
|
|
197
|
+
getTransferPayload(rawAmount, notificationReceiverAddress, responseAddress, evmData, crossChainTonAmount, forwardFeeAmount, feeData) {
|
|
198
|
+
const queryId = (0, Utils_1.generateRandomNumberByTimestamp)().randomNumber;
|
|
199
|
+
return JettonWallet_1.JettonWallet.transferMessage(rawAmount, notificationReceiverAddress, responseAddress, Consts_1.JETTON_TRANSFER_FORWARD_TON_AMOUNT + forwardFeeAmount + crossChainTonAmount, crossChainTonAmount, feeData, evmData, queryId);
|
|
200
|
+
}
|
|
201
|
+
getBurnPayload(rawAmount, notificationReceiverAddress, evmData, crossChainTonAmount, feeData) {
|
|
202
|
+
const queryId = (0, Utils_1.generateRandomNumberByTimestamp)().randomNumber;
|
|
203
|
+
return JettonWallet_1.JettonWallet.burnMessage(rawAmount, notificationReceiverAddress, crossChainTonAmount, feeData, evmData, queryId);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
exports.FT = FT;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Address, Cell } from '@ton/ton';
|
|
2
|
+
import { IConfiguration } from '../structs/Services';
|
|
3
|
+
import { Asset, AssetType, ContractOpener, EVMAddress, FeeParams, NFTItemData, Origin, TVMAddress } from '../structs/Struct';
|
|
4
|
+
export declare class NFT implements Asset {
|
|
5
|
+
private _addresses;
|
|
6
|
+
readonly origin: Origin;
|
|
7
|
+
readonly type: AssetType;
|
|
8
|
+
private _nftCollection;
|
|
9
|
+
private _configuration;
|
|
10
|
+
/**
|
|
11
|
+
* @description Create NFT from item address. Item MUST BE deployed on TON.
|
|
12
|
+
* @param configuration - Configuration
|
|
13
|
+
* @param item - Item address (TVM address)
|
|
14
|
+
* @param origin - Origin
|
|
15
|
+
* @returns NFT
|
|
16
|
+
*/
|
|
17
|
+
static fromItem(configuration: IConfiguration, item: TVMAddress): Promise<NFT>;
|
|
18
|
+
/**
|
|
19
|
+
* @description Create NFT from collection address. TON-native assets MUST BE deployed on TON.
|
|
20
|
+
* @param configuration - Configuration
|
|
21
|
+
* @param item - Item address (TVM address)
|
|
22
|
+
* @param origin - Origin
|
|
23
|
+
* @returns NFT
|
|
24
|
+
*/
|
|
25
|
+
static fromCollection(configuration: IConfiguration, item: {
|
|
26
|
+
collection: TVMAddress | EVMAddress;
|
|
27
|
+
index: bigint;
|
|
28
|
+
}): Promise<NFT>;
|
|
29
|
+
static getItemData(contractOpener: ContractOpener, itemAddress: TVMAddress): Promise<NFTItemData>;
|
|
30
|
+
static getCollectionData(contractOpener: ContractOpener, collectionAddress: TVMAddress): Promise<{
|
|
31
|
+
nextIndex: number;
|
|
32
|
+
content: Cell;
|
|
33
|
+
ownerAddress: Address;
|
|
34
|
+
}>;
|
|
35
|
+
static getOrigin(configuration: IConfiguration, itemOrCollection: TVMAddress): Promise<Origin>;
|
|
36
|
+
static getItemAddress(contractOpener: ContractOpener, collectionAddress: TVMAddress, index: bigint): Promise<string>;
|
|
37
|
+
static getTVMAddress(configuration: IConfiguration, collectionAddress: EVMAddress, tokenId?: bigint): Promise<string>;
|
|
38
|
+
constructor(nftAddress: {
|
|
39
|
+
item: TVMAddress;
|
|
40
|
+
collection: TVMAddress;
|
|
41
|
+
index: bigint;
|
|
42
|
+
evmAddress?: EVMAddress;
|
|
43
|
+
}, origin: Origin, configuration: IConfiguration);
|
|
44
|
+
get addresses(): {
|
|
45
|
+
item: string;
|
|
46
|
+
collection: string;
|
|
47
|
+
index: bigint;
|
|
48
|
+
evmAddress?: string;
|
|
49
|
+
};
|
|
50
|
+
get address(): string;
|
|
51
|
+
get rawAmount(): bigint;
|
|
52
|
+
get clone(): NFT;
|
|
53
|
+
withAmount(): Promise<NFT>;
|
|
54
|
+
addAmount(): Promise<NFT>;
|
|
55
|
+
getEVMAddress(): Promise<string>;
|
|
56
|
+
getTVMAddress(): Promise<string>;
|
|
57
|
+
generatePayload(params: {
|
|
58
|
+
excessReceiver: string;
|
|
59
|
+
evmData: Cell;
|
|
60
|
+
crossChainTonAmount?: bigint;
|
|
61
|
+
forwardFeeTonAmount?: bigint;
|
|
62
|
+
feeParams?: FeeParams;
|
|
63
|
+
}): Promise<Cell>;
|
|
64
|
+
isOwnedBy(userAddress: string): Promise<boolean>;
|
|
65
|
+
checkCanBeTransferedBy(userAddress: string): Promise<void>;
|
|
66
|
+
getBalanceOf(userAddress: string): Promise<bigint>;
|
|
67
|
+
private getBurnPayload;
|
|
68
|
+
private getTransferPayload;
|
|
69
|
+
}
|