@tonappchain/sdk 0.6.1-v3.0.1 → 0.6.1-v3.0.3
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 +19 -0
- package/dist/adapters/contractOpener.js +94 -0
- package/dist/errors/errors.d.ts +34 -0
- package/dist/errors/errors.js +80 -0
- package/dist/errors/index.d.ts +2 -0
- package/dist/errors/index.js +30 -0
- package/dist/errors/instances.d.ts +17 -0
- package/dist/errors/instances.js +29 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +35 -0
- package/dist/sdk/Consts.d.ts +7 -0
- package/dist/sdk/Consts.js +11 -0
- package/dist/sdk/OperationTracker.d.ts +14 -0
- package/dist/sdk/OperationTracker.js +151 -0
- package/dist/sdk/StartTracking.d.ts +8 -0
- package/dist/sdk/StartTracking.js +127 -0
- package/dist/sdk/TacSdk.d.ts +53 -0
- package/dist/sdk/TacSdk.js +713 -0
- package/dist/sdk/Utils.d.ts +18 -0
- package/dist/sdk/Utils.js +128 -0
- package/dist/sender/RawSender.d.ts +14 -0
- package/dist/sender/RawSender.js +70 -0
- package/dist/sender/SenderAbstraction.d.ts +20 -0
- package/dist/sender/SenderAbstraction.js +5 -0
- package/dist/sender/SenderFactory.d.ts +33 -0
- package/dist/sender/SenderFactory.js +55 -0
- package/dist/sender/TonConnectSender.d.ts +12 -0
- package/dist/sender/TonConnectSender.js +55 -0
- package/dist/sender/index.d.ts +2 -0
- package/dist/sender/index.js +18 -0
- package/dist/structs/InternalStruct.d.ts +82 -0
- package/dist/structs/InternalStruct.js +10 -0
- package/dist/structs/Struct.d.ts +334 -0
- package/dist/structs/Struct.js +53 -0
- package/dist/wrappers/ContentUtils.d.ts +25 -0
- package/dist/wrappers/ContentUtils.js +160 -0
- package/dist/wrappers/HighloadQueryId.d.ts +17 -0
- package/dist/wrappers/HighloadQueryId.js +72 -0
- package/dist/wrappers/HighloadWalletV3.d.ts +61 -0
- package/dist/wrappers/HighloadWalletV3.js +161 -0
- package/dist/wrappers/JettonMaster.d.ts +24 -0
- package/dist/wrappers/JettonMaster.js +53 -0
- package/dist/wrappers/JettonWallet.d.ts +47 -0
- package/dist/wrappers/JettonWallet.js +107 -0
- package/dist/wrappers/Settings.d.ts +10 -0
- package/dist/wrappers/Settings.js +38 -0
- package/package.json +2 -2
|
@@ -0,0 +1,713 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TacSdk = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const ton_1 = require("@ton/ton");
|
|
9
|
+
const ethers_1 = require("ethers");
|
|
10
|
+
// import structs
|
|
11
|
+
const Struct_1 = require("../structs/Struct");
|
|
12
|
+
// import internal structs
|
|
13
|
+
const InternalStruct_1 = require("../structs/InternalStruct");
|
|
14
|
+
// jetton imports
|
|
15
|
+
const JettonMaster_1 = require("../wrappers/JettonMaster");
|
|
16
|
+
const JettonWallet_1 = require("../wrappers/JettonWallet");
|
|
17
|
+
// ton settings
|
|
18
|
+
const Settings_1 = require("../wrappers/Settings");
|
|
19
|
+
const Consts_1 = require("./Consts");
|
|
20
|
+
const Utils_1 = require("./Utils");
|
|
21
|
+
const artifacts_1 = require("@tonappchain/artifacts");
|
|
22
|
+
const errors_1 = require("../errors");
|
|
23
|
+
const contractOpener_1 = require("../adapters/contractOpener");
|
|
24
|
+
const wrappers_1 = require("@tonappchain/artifacts/dist/src/ton/wrappers");
|
|
25
|
+
const instances_1 = require("../errors/instances");
|
|
26
|
+
class TacSdk {
|
|
27
|
+
constructor(network, delay, artifacts, TONParams, TACParams, liteSequencerEndpoints) {
|
|
28
|
+
this.network = network;
|
|
29
|
+
this.delay = delay;
|
|
30
|
+
this.artifacts = artifacts;
|
|
31
|
+
this.TONParams = TONParams;
|
|
32
|
+
this.TACParams = TACParams;
|
|
33
|
+
this.liteSequencerEndpoints = liteSequencerEndpoints;
|
|
34
|
+
}
|
|
35
|
+
static async create(sdkParams) {
|
|
36
|
+
const network = sdkParams.network;
|
|
37
|
+
const delay = sdkParams.delay ?? Consts_1.DEFAULT_DELAY;
|
|
38
|
+
const artifacts = network === Struct_1.Network.TESTNET ? artifacts_1.testnet : artifacts_1.mainnet;
|
|
39
|
+
const TONParams = await this.prepareTONParams(network, delay, artifacts, sdkParams.TONParams);
|
|
40
|
+
const TACParams = await this.prepareTACParams(artifacts, delay, sdkParams.TACParams);
|
|
41
|
+
const liteSequencerEndpoints = sdkParams.customLiteSequencerEndpoints ??
|
|
42
|
+
(network === Struct_1.Network.TESTNET
|
|
43
|
+
? artifacts_1.testnet.PUBLIC_LITE_SEQUENCER_ENDPOINTS
|
|
44
|
+
: artifacts_1.mainnet.PUBLIC_LITE_SEQUENCER_ENDPOINTS);
|
|
45
|
+
return new TacSdk(network, delay, artifacts, TONParams, TACParams, liteSequencerEndpoints);
|
|
46
|
+
}
|
|
47
|
+
static async prepareTONParams(network, delay, artifacts, TONParams) {
|
|
48
|
+
const contractOpener = TONParams?.contractOpener ?? (await (0, contractOpener_1.orbsOpener4)(network));
|
|
49
|
+
const settingsAddress = TONParams?.settingsAddress ?? artifacts.ton.addresses.TON_SETTINGS_ADDRESS;
|
|
50
|
+
const settings = contractOpener.open(new Settings_1.Settings(ton_1.Address.parse(settingsAddress)));
|
|
51
|
+
const jettonProxyAddress = await settings.getAddressSetting('JettonProxyAddress');
|
|
52
|
+
await (0, Utils_1.sleep)(delay * 1000);
|
|
53
|
+
const crossChainLayerAddress = await settings.getAddressSetting('CrossChainLayerAddress');
|
|
54
|
+
await (0, Utils_1.sleep)(delay * 1000);
|
|
55
|
+
const jettonMinterCode = await settings.getCellSetting('JettonMinterCode');
|
|
56
|
+
await (0, Utils_1.sleep)(delay * 1000);
|
|
57
|
+
const jettonWalletCode = await settings.getCellSetting('JettonWalletCode');
|
|
58
|
+
await (0, Utils_1.sleep)(delay * 1000);
|
|
59
|
+
const nftProxyAddress = await settings.getAddressSetting('NFTProxyAddress');
|
|
60
|
+
await (0, Utils_1.sleep)(delay * 1000);
|
|
61
|
+
const nftItemCode = await settings.getCellSetting('NFTItemCode');
|
|
62
|
+
await (0, Utils_1.sleep)(delay * 1000);
|
|
63
|
+
const nftCollectionCode = await settings.getCellSetting('NFTCollectionCode');
|
|
64
|
+
await (0, Utils_1.sleep)(delay * 1000);
|
|
65
|
+
return {
|
|
66
|
+
contractOpener,
|
|
67
|
+
jettonProxyAddress,
|
|
68
|
+
crossChainLayerAddress,
|
|
69
|
+
jettonMinterCode,
|
|
70
|
+
jettonWalletCode,
|
|
71
|
+
nftProxyAddress,
|
|
72
|
+
nftItemCode,
|
|
73
|
+
nftCollectionCode,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
static async prepareTACParams(artifacts, delay, TACParams) {
|
|
77
|
+
const provider = TACParams?.provider ?? ethers_1.ethers.getDefaultProvider(artifacts.TAC_RPC_ENDPOINT);
|
|
78
|
+
const settingsAddress = TACParams?.settingsAddress?.toString() ?? artifacts.tac.addresses.TAC_SETTINGS_ADDRESS;
|
|
79
|
+
const settings = artifacts.tac.wrappers.SettingsFactoryTAC.connect(settingsAddress, provider);
|
|
80
|
+
const crossChainLayerABI = TACParams?.crossChainLayerABI ?? artifacts.tac.compilationArtifacts.CrossChainLayer.abi;
|
|
81
|
+
const crossChainLayerAddress = await settings.getAddressSetting((0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)('CrossChainLayerAddress')));
|
|
82
|
+
const crossChainLayer = artifacts.tac.wrappers.CrossChainLayerFactoryTAC.connect(crossChainLayerAddress, provider);
|
|
83
|
+
await (0, Utils_1.sleep)(delay * 1000);
|
|
84
|
+
const tokenUtilsAddress = await settings.getAddressSetting((0, ethers_1.keccak256)((0, ethers_1.toUtf8Bytes)('TokenUtilsAddress')));
|
|
85
|
+
const tokenUtils = artifacts.tac.wrappers.TokenUtilsFactoryTAC.connect(tokenUtilsAddress, provider);
|
|
86
|
+
await (0, Utils_1.sleep)(delay * 1000);
|
|
87
|
+
const trustedTACExecutors = await settings.getTrustedEVMExecutors();
|
|
88
|
+
await (0, Utils_1.sleep)(delay * 1000);
|
|
89
|
+
const trustedTONExecutors = await settings.getTrustedTVMExecutors();
|
|
90
|
+
const crossChainLayerTokenABI = TACParams?.crossChainLayerTokenABI ?? artifacts.tac.compilationArtifacts.CrossChainLayerToken.abi;
|
|
91
|
+
const crossChainLayerTokenBytecode = TACParams?.crossChainLayerTokenBytecode ?? artifacts.tac.compilationArtifacts.CrossChainLayerToken.bytecode;
|
|
92
|
+
const crossChainLayerNFTABI = TACParams?.crossChainLayerNFTABI ?? artifacts.tac.compilationArtifacts.CrossChainLayerNFT.abi;
|
|
93
|
+
const crossChainLayerNFTBytecode = TACParams?.crossChainLayerNFTBytecode ?? artifacts.tac.compilationArtifacts.CrossChainLayerNFT.bytecode;
|
|
94
|
+
return {
|
|
95
|
+
provider,
|
|
96
|
+
settings,
|
|
97
|
+
tokenUtils,
|
|
98
|
+
crossChainLayer,
|
|
99
|
+
trustedTACExecutors,
|
|
100
|
+
trustedTONExecutors,
|
|
101
|
+
abiCoder: new ethers_1.ethers.AbiCoder(),
|
|
102
|
+
crossChainLayerABI,
|
|
103
|
+
crossChainLayerTokenABI,
|
|
104
|
+
crossChainLayerTokenBytecode,
|
|
105
|
+
crossChainLayerNFTABI,
|
|
106
|
+
crossChainLayerNFTBytecode,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
closeConnections() {
|
|
110
|
+
return this.TONParams.contractOpener.closeConnections?.call(this);
|
|
111
|
+
}
|
|
112
|
+
get nativeTONAddress() {
|
|
113
|
+
return 'NONE';
|
|
114
|
+
}
|
|
115
|
+
async nativeTACAddress() {
|
|
116
|
+
return this.TACParams.crossChainLayer.NATIVE_TOKEN_ADDRESS.staticCall();
|
|
117
|
+
}
|
|
118
|
+
async getUserJettonWalletAddress(userAddress, tokenAddress) {
|
|
119
|
+
const jettonMaster = this.TONParams.contractOpener.open(new JettonMaster_1.JettonMaster(ton_1.Address.parse(tokenAddress)));
|
|
120
|
+
return jettonMaster.getWalletAddress(userAddress);
|
|
121
|
+
}
|
|
122
|
+
async getUserJettonBalance(userAddress, tokenAddress) {
|
|
123
|
+
const jettonMaster = this.TONParams.contractOpener.open(new JettonMaster_1.JettonMaster(ton_1.Address.parse(tokenAddress)));
|
|
124
|
+
const userJettonWalletAddress = await jettonMaster.getWalletAddress(userAddress);
|
|
125
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
126
|
+
const userJettonWallet = this.TONParams.contractOpener.open(new JettonWallet_1.JettonWallet(ton_1.Address.parse(userJettonWalletAddress)));
|
|
127
|
+
return userJettonWallet.getJettonBalance();
|
|
128
|
+
}
|
|
129
|
+
async getUserJettonBalanceExtended(userAddress, tokenAddress) {
|
|
130
|
+
const masterAddress = ton_1.Address.parse(tokenAddress);
|
|
131
|
+
const masterState = await this.TONParams.contractOpener.getContractState(masterAddress);
|
|
132
|
+
if (masterState.state !== 'active') {
|
|
133
|
+
return { exists: false };
|
|
134
|
+
}
|
|
135
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
136
|
+
const jettonMaster = this.TONParams.contractOpener.open(new JettonMaster_1.JettonMaster(masterAddress));
|
|
137
|
+
const userJettonWalletAddress = await jettonMaster.getWalletAddress(userAddress);
|
|
138
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
139
|
+
const userJettonWallet = this.TONParams.contractOpener.open(new JettonWallet_1.JettonWallet(ton_1.Address.parse(userJettonWalletAddress)));
|
|
140
|
+
const rawAmount = await userJettonWallet.getJettonBalance();
|
|
141
|
+
const decimalsRaw = (await jettonMaster.getJettonData()).content.metadata.decimals;
|
|
142
|
+
const decimals = decimalsRaw ? Number(decimalsRaw) : 9;
|
|
143
|
+
return {
|
|
144
|
+
rawAmount,
|
|
145
|
+
decimals,
|
|
146
|
+
amount: (0, Utils_1.calculateAmount)(rawAmount, decimals),
|
|
147
|
+
exists: true,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
getJettonTransferPayload(jettonData, responseAddress, evmData, crossChainTonAmount, forwardFeeAmount, feeData) {
|
|
151
|
+
const queryId = (0, Utils_1.generateRandomNumberByTimestamp)().randomNumber;
|
|
152
|
+
return JettonWallet_1.JettonWallet.transferMessage(jettonData.rawAmount, this.TONParams.jettonProxyAddress, responseAddress, Consts_1.JETTON_TRANSFER_FORWARD_TON_AMOUNT + forwardFeeAmount + crossChainTonAmount, crossChainTonAmount, feeData, evmData, queryId);
|
|
153
|
+
}
|
|
154
|
+
getJettonBurnPayload(jettonData, evmData, crossChainTonAmount, feeData) {
|
|
155
|
+
const queryId = (0, Utils_1.generateRandomNumberByTimestamp)().randomNumber;
|
|
156
|
+
return JettonWallet_1.JettonWallet.burnMessage(jettonData.rawAmount, jettonData.notificationReceiverAddress, crossChainTonAmount, feeData, evmData, queryId);
|
|
157
|
+
}
|
|
158
|
+
getNFTBurnPayload(burnData) {
|
|
159
|
+
const queryId = (0, Utils_1.generateRandomNumberByTimestamp)().randomNumber;
|
|
160
|
+
return wrappers_1.NFTItem.burnMessage(queryId, (0, ton_1.address)(burnData.notificationReceiverAddress), burnData.crossChainTonAmount ?? 0, burnData.evmData, burnData.feeData);
|
|
161
|
+
}
|
|
162
|
+
getNFTTransferPayload(transferData, forwardFeeAmount) {
|
|
163
|
+
const queryId = (0, Utils_1.generateRandomNumberByTimestamp)().randomNumber;
|
|
164
|
+
const crossChainTonAmount = transferData.crossChainTonAmount ?? 0n;
|
|
165
|
+
const forwardPayload = (0, ton_1.beginCell)()
|
|
166
|
+
.storeCoins(crossChainTonAmount)
|
|
167
|
+
.storeMaybeRef(transferData.feeData)
|
|
168
|
+
.storeMaybeRef(transferData.evmData)
|
|
169
|
+
.endCell();
|
|
170
|
+
return wrappers_1.NFTItem.transferMessage(queryId, (0, ton_1.address)(transferData.to ?? this.TONParams.nftProxyAddress), (0, ton_1.address)(transferData.responseAddress), Number((0, ton_1.fromNano)(Consts_1.NFT_TRANSFER_FORWARD_TON_AMOUNT + forwardFeeAmount + crossChainTonAmount)), forwardPayload);
|
|
171
|
+
}
|
|
172
|
+
generateFeeData(feeParams) {
|
|
173
|
+
if (feeParams) {
|
|
174
|
+
let feeDataBuilder = (0, ton_1.beginCell)()
|
|
175
|
+
.storeBit(feeParams.isRoundTrip)
|
|
176
|
+
.storeCoins(feeParams.protocolFee)
|
|
177
|
+
.storeCoins(feeParams.evmExecutorFee);
|
|
178
|
+
if (feeParams.isRoundTrip) {
|
|
179
|
+
feeDataBuilder.storeCoins(feeParams.tvmExecutorFee);
|
|
180
|
+
}
|
|
181
|
+
return feeDataBuilder.endCell();
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
getTonTransferPayload(responseAddress, evmData, crossChainTonAmount, feeParams) {
|
|
188
|
+
const queryId = (0, Utils_1.generateRandomNumberByTimestamp)().randomNumber;
|
|
189
|
+
const feeData = this.generateFeeData(feeParams);
|
|
190
|
+
return (0, ton_1.beginCell)()
|
|
191
|
+
.storeUint(this.artifacts.ton.wrappers.CrossChainLayerOpCodes.anyone_tvmMsgToEVM, 32)
|
|
192
|
+
.storeUint(queryId, 64)
|
|
193
|
+
.storeUint(this.artifacts.ton.wrappers.OperationType.tonTransfer, 32)
|
|
194
|
+
.storeCoins(crossChainTonAmount)
|
|
195
|
+
.storeMaybeRef(feeData)
|
|
196
|
+
.storeAddress(ton_1.Address.parse(responseAddress))
|
|
197
|
+
.storeMaybeRef(evmData)
|
|
198
|
+
.endCell();
|
|
199
|
+
}
|
|
200
|
+
async getJettonOpType(asset) {
|
|
201
|
+
const { code: givenMinterCodeBOC } = await this.TONParams.contractOpener.getContractState((0, ton_1.address)(asset.address));
|
|
202
|
+
if (!givenMinterCodeBOC) {
|
|
203
|
+
throw errors_1.emptyContractError;
|
|
204
|
+
}
|
|
205
|
+
const givenMinterCode = ton_1.Cell.fromBoc(givenMinterCodeBOC)[0];
|
|
206
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
207
|
+
if (!this.TONParams.jettonMinterCode.equals(givenMinterCode)) {
|
|
208
|
+
return InternalStruct_1.AssetOpType.JETTON_TRANSFER;
|
|
209
|
+
}
|
|
210
|
+
const givenMinter = this.TONParams.contractOpener.open(new JettonMaster_1.JettonMaster((0, ton_1.address)(asset.address)));
|
|
211
|
+
const evmAddress = await givenMinter.getEVMAddress();
|
|
212
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
213
|
+
const expectedMinterAddress = await (0, Utils_1.calculateContractAddress)(this.TONParams.jettonMinterCode, (0, ton_1.beginCell)()
|
|
214
|
+
.storeCoins(0)
|
|
215
|
+
.storeAddress((0, ton_1.address)(this.TONParams.crossChainLayerAddress))
|
|
216
|
+
.storeAddress(null)
|
|
217
|
+
.storeRef((0, ton_1.beginCell)().endCell())
|
|
218
|
+
.storeRef(this.TONParams.jettonWalletCode)
|
|
219
|
+
.storeStringTail(evmAddress)
|
|
220
|
+
.endCell());
|
|
221
|
+
if (!expectedMinterAddress.equals(givenMinter.address)) {
|
|
222
|
+
return InternalStruct_1.AssetOpType.JETTON_TRANSFER;
|
|
223
|
+
}
|
|
224
|
+
return InternalStruct_1.AssetOpType.JETTON_BURN;
|
|
225
|
+
}
|
|
226
|
+
async getNFTOpType(asset) {
|
|
227
|
+
const { code: itemCodeBOC } = await this.TONParams.contractOpener.getContractState((0, ton_1.address)(asset.address));
|
|
228
|
+
if (!itemCodeBOC) {
|
|
229
|
+
throw errors_1.emptyContractError;
|
|
230
|
+
}
|
|
231
|
+
const givenNFTItemCode = ton_1.Cell.fromBoc(itemCodeBOC)[0];
|
|
232
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
233
|
+
if (!this.TONParams.nftItemCode.equals(givenNFTItemCode)) {
|
|
234
|
+
return InternalStruct_1.AssetOpType.NFT_TRANSFER;
|
|
235
|
+
}
|
|
236
|
+
return InternalStruct_1.AssetOpType.NFT_BURN;
|
|
237
|
+
}
|
|
238
|
+
async getNFTItemAddressTON(collectionAddress, itemIndex) {
|
|
239
|
+
(0, Utils_1.validateTVMAddress)(collectionAddress);
|
|
240
|
+
const nftCollection = this.TONParams.contractOpener.open(wrappers_1.NFTCollection.createFromAddress((0, ton_1.address)(collectionAddress)));
|
|
241
|
+
return (await nftCollection.getNFTAddressByIndex(itemIndex)).toString();
|
|
242
|
+
}
|
|
243
|
+
async getNFTItemData(itemAddress) {
|
|
244
|
+
(0, Utils_1.validateTVMAddress)(itemAddress);
|
|
245
|
+
const nftItem = this.TONParams.contractOpener.open(wrappers_1.NFTItem.createFromAddress((0, ton_1.address)(itemAddress)));
|
|
246
|
+
return await nftItem.getNFTData();
|
|
247
|
+
}
|
|
248
|
+
async aggregateTokens(assets) {
|
|
249
|
+
const uniqueAssetsMap = new Map();
|
|
250
|
+
let crossChainTonAmount = 0n;
|
|
251
|
+
for await (const asset of assets ?? []) {
|
|
252
|
+
if (asset.rawAmount <= 0)
|
|
253
|
+
continue;
|
|
254
|
+
if (asset.type !== Struct_1.AssetType.FT)
|
|
255
|
+
continue;
|
|
256
|
+
if (asset.address) {
|
|
257
|
+
(0, Utils_1.validateTVMAddress)(asset.address);
|
|
258
|
+
uniqueAssetsMap.set(asset.address, (uniqueAssetsMap.get(asset.address) || 0n) + BigInt(asset.rawAmount));
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
crossChainTonAmount += BigInt(asset.rawAmount);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const jettons = Array.from(uniqueAssetsMap.entries()).map(([address, rawAmount]) => ({
|
|
265
|
+
address,
|
|
266
|
+
rawAmount,
|
|
267
|
+
type: Struct_1.AssetType.FT,
|
|
268
|
+
}));
|
|
269
|
+
uniqueAssetsMap.clear();
|
|
270
|
+
for await (const asset of assets ?? []) {
|
|
271
|
+
if (asset.type !== Struct_1.AssetType.NFT)
|
|
272
|
+
continue;
|
|
273
|
+
(0, Utils_1.validateTVMAddress)(asset.address);
|
|
274
|
+
uniqueAssetsMap.set(asset.address, 1n);
|
|
275
|
+
}
|
|
276
|
+
const nfts = Array.from(uniqueAssetsMap.entries()).map(([address, rawAmount]) => ({
|
|
277
|
+
address,
|
|
278
|
+
rawAmount,
|
|
279
|
+
type: Struct_1.AssetType.NFT,
|
|
280
|
+
}));
|
|
281
|
+
return {
|
|
282
|
+
jettons,
|
|
283
|
+
nfts,
|
|
284
|
+
crossChainTonAmount,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
async generateJettonPayload(jetton, caller, evmData, crossChainTonAmount, forwardFeeTonAmount, feeParams) {
|
|
288
|
+
const opType = await this.getJettonOpType(jetton);
|
|
289
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
290
|
+
console.log(`***** Jetton ${jetton.address} requires ${opType} operation`);
|
|
291
|
+
const feeData = this.generateFeeData(feeParams);
|
|
292
|
+
let payload;
|
|
293
|
+
switch (opType) {
|
|
294
|
+
case InternalStruct_1.AssetOpType.JETTON_BURN:
|
|
295
|
+
payload = this.getJettonBurnPayload({
|
|
296
|
+
notificationReceiverAddress: this.TONParams.crossChainLayerAddress,
|
|
297
|
+
...jetton,
|
|
298
|
+
}, evmData, crossChainTonAmount, feeData);
|
|
299
|
+
break;
|
|
300
|
+
case InternalStruct_1.AssetOpType.JETTON_TRANSFER:
|
|
301
|
+
payload = this.getJettonTransferPayload(jetton, caller, evmData, crossChainTonAmount, forwardFeeTonAmount, feeData);
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
return payload;
|
|
305
|
+
}
|
|
306
|
+
async generateNFTPayload(nft, caller, evmData, crossChainTonAmount, forwardFeeTonAmount, feeParams) {
|
|
307
|
+
const opType = await this.getNFTOpType(nft);
|
|
308
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
309
|
+
console.log(`***** NFT ${nft.address} requires ${opType} operation`);
|
|
310
|
+
const feeData = this.generateFeeData(feeParams);
|
|
311
|
+
let payload;
|
|
312
|
+
switch (opType) {
|
|
313
|
+
case InternalStruct_1.AssetOpType.NFT_BURN:
|
|
314
|
+
payload = this.getNFTBurnPayload({
|
|
315
|
+
notificationReceiverAddress: this.TONParams.crossChainLayerAddress,
|
|
316
|
+
...nft,
|
|
317
|
+
evmData,
|
|
318
|
+
crossChainTonAmount,
|
|
319
|
+
feeData,
|
|
320
|
+
});
|
|
321
|
+
break;
|
|
322
|
+
case InternalStruct_1.AssetOpType.NFT_TRANSFER:
|
|
323
|
+
payload = this.getNFTTransferPayload({
|
|
324
|
+
to: this.TONParams.nftProxyAddress,
|
|
325
|
+
responseAddress: caller,
|
|
326
|
+
evmData,
|
|
327
|
+
crossChainTonAmount,
|
|
328
|
+
feeData,
|
|
329
|
+
...nft,
|
|
330
|
+
}, forwardFeeTonAmount);
|
|
331
|
+
break;
|
|
332
|
+
}
|
|
333
|
+
return payload;
|
|
334
|
+
}
|
|
335
|
+
async generateCrossChainMessages(caller, evmData, aggregatedData, feeParams) {
|
|
336
|
+
let crossChainTonAmount = aggregatedData.crossChainTonAmount;
|
|
337
|
+
let feeTonAmount = feeParams.protocolFee + feeParams.evmExecutorFee + feeParams.tvmExecutorFee;
|
|
338
|
+
if (aggregatedData.jettons.length == 0 && aggregatedData.nfts.length == 0) {
|
|
339
|
+
return [
|
|
340
|
+
{
|
|
341
|
+
address: this.TONParams.crossChainLayerAddress,
|
|
342
|
+
value: crossChainTonAmount + feeTonAmount + Consts_1.TRANSACTION_TON_AMOUNT,
|
|
343
|
+
payload: this.getTonTransferPayload(caller, evmData, crossChainTonAmount, feeParams),
|
|
344
|
+
},
|
|
345
|
+
];
|
|
346
|
+
}
|
|
347
|
+
const messages = [];
|
|
348
|
+
let currentFeeParams = feeParams;
|
|
349
|
+
for (const jetton of aggregatedData.jettons) {
|
|
350
|
+
const payload = await this.generateJettonPayload(jetton, caller, evmData, crossChainTonAmount, feeTonAmount, currentFeeParams);
|
|
351
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
352
|
+
const jettonWalletAddress = await this.getUserJettonWalletAddress(caller, jetton.address);
|
|
353
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
354
|
+
messages.push({
|
|
355
|
+
address: jettonWalletAddress,
|
|
356
|
+
value: crossChainTonAmount + feeTonAmount + Consts_1.TRANSACTION_TON_AMOUNT,
|
|
357
|
+
payload,
|
|
358
|
+
});
|
|
359
|
+
crossChainTonAmount = 0n;
|
|
360
|
+
feeTonAmount = 0n;
|
|
361
|
+
currentFeeParams = undefined;
|
|
362
|
+
}
|
|
363
|
+
for (const nft of aggregatedData.nfts) {
|
|
364
|
+
const payload = await this.generateNFTPayload(nft, caller, evmData, crossChainTonAmount, feeTonAmount, currentFeeParams);
|
|
365
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
366
|
+
messages.push({
|
|
367
|
+
address: nft.address,
|
|
368
|
+
value: crossChainTonAmount + feeTonAmount + Consts_1.TRANSACTION_TON_AMOUNT,
|
|
369
|
+
payload,
|
|
370
|
+
});
|
|
371
|
+
crossChainTonAmount = 0n;
|
|
372
|
+
feeTonAmount = 0n;
|
|
373
|
+
currentFeeParams = undefined;
|
|
374
|
+
}
|
|
375
|
+
return messages;
|
|
376
|
+
}
|
|
377
|
+
async getRawAmount(asset, precalculatedAddress) {
|
|
378
|
+
if ('rawAmount' in asset) {
|
|
379
|
+
// User specified raw format amount
|
|
380
|
+
return asset.rawAmount;
|
|
381
|
+
}
|
|
382
|
+
if (!precalculatedAddress) {
|
|
383
|
+
// User specified TON Coin
|
|
384
|
+
return (0, ton_1.toNano)(asset.amount);
|
|
385
|
+
}
|
|
386
|
+
if (typeof asset.decimals === 'number') {
|
|
387
|
+
// User manually set decimals
|
|
388
|
+
return (0, Utils_1.calculateRawAmount)(asset.amount, asset.decimals);
|
|
389
|
+
}
|
|
390
|
+
// Get decimals from chain
|
|
391
|
+
(0, Utils_1.validateTVMAddress)(precalculatedAddress);
|
|
392
|
+
const contract = this.TONParams.contractOpener.open(new JettonMaster_1.JettonMaster((0, ton_1.address)(precalculatedAddress)));
|
|
393
|
+
const { content } = await contract.getJettonData();
|
|
394
|
+
if (!content.metadata.decimals) {
|
|
395
|
+
// if decimals not specified use default value 9
|
|
396
|
+
return (0, ton_1.toNano)(asset.amount);
|
|
397
|
+
}
|
|
398
|
+
return (0, Utils_1.calculateRawAmount)(asset.amount, Number(content.metadata.decimals));
|
|
399
|
+
}
|
|
400
|
+
async convertAssetsToRawFormat(assets) {
|
|
401
|
+
return await Promise.all((assets ?? []).map(async (asset) => {
|
|
402
|
+
if (asset.type === Struct_1.AssetType.FT) {
|
|
403
|
+
const address = (0, ethers_1.isAddress)(asset.address)
|
|
404
|
+
? await this.getTVMTokenAddress(asset.address)
|
|
405
|
+
: asset.address;
|
|
406
|
+
return {
|
|
407
|
+
address,
|
|
408
|
+
rawAmount: await this.getRawAmount(asset, address),
|
|
409
|
+
type: asset.type,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
if (asset.type === Struct_1.AssetType.NFT) {
|
|
413
|
+
if ('collectionAddress' in asset) {
|
|
414
|
+
const address = (0, ethers_1.isAddress)(asset.collectionAddress)
|
|
415
|
+
? await this.getTVMNFTAddress(asset.collectionAddress, asset.itemIndex)
|
|
416
|
+
: await this.getNFTItemAddressTON(asset.collectionAddress, asset.itemIndex);
|
|
417
|
+
return {
|
|
418
|
+
address,
|
|
419
|
+
rawAmount: 1n,
|
|
420
|
+
type: asset.type,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
(0, Utils_1.validateTVMAddress)(asset.address);
|
|
424
|
+
return {
|
|
425
|
+
address: asset.address,
|
|
426
|
+
rawAmount: 1n,
|
|
427
|
+
type: asset.type,
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
throw instances_1.invalidAssetType;
|
|
431
|
+
}));
|
|
432
|
+
}
|
|
433
|
+
async getFeeInfo(evmProxyMsg, transactionLinker, rawAssets, evmValidExecutors, forceSend = false, isRoundTrip) {
|
|
434
|
+
const crossChainLayer = this.TONParams.contractOpener.open(this.artifacts.ton.wrappers.CrossChainLayer.createFromAddress(ton_1.Address.parse(this.TONParams.crossChainLayerAddress)));
|
|
435
|
+
const fullStateCCL = await crossChainLayer.getFullData();
|
|
436
|
+
const tacSimulationBody = {
|
|
437
|
+
tacCallParams: {
|
|
438
|
+
arguments: evmProxyMsg.encodedParameters ?? '0x',
|
|
439
|
+
methodName: (0, Utils_1.formatSolidityMethodName)(evmProxyMsg.methodName),
|
|
440
|
+
target: evmProxyMsg.evmTargetAddress,
|
|
441
|
+
},
|
|
442
|
+
evmValidExecutors: evmValidExecutors,
|
|
443
|
+
extraData: '0x',
|
|
444
|
+
feeAssetAddress: '',
|
|
445
|
+
shardsKey: transactionLinker.shardsKey,
|
|
446
|
+
tonAssets: rawAssets.map((asset) => ({
|
|
447
|
+
amount: asset.rawAmount.toString(),
|
|
448
|
+
tokenAddress: asset.address || '',
|
|
449
|
+
assetType: asset.type,
|
|
450
|
+
})),
|
|
451
|
+
tonCaller: transactionLinker.caller,
|
|
452
|
+
};
|
|
453
|
+
const tacSimulationResult = await this.simulateTACMessage(tacSimulationBody);
|
|
454
|
+
if (!tacSimulationResult.simulationStatus) {
|
|
455
|
+
if (forceSend) {
|
|
456
|
+
return {
|
|
457
|
+
feeParams: {
|
|
458
|
+
isRoundTrip: isRoundTrip ?? false,
|
|
459
|
+
gasLimit: 0n,
|
|
460
|
+
protocolFee: BigInt((0, ton_1.toNano)(fullStateCCL.tacProtocolFee)) +
|
|
461
|
+
BigInt(isRoundTrip ?? false) * BigInt((0, ton_1.toNano)(fullStateCCL.tonProtocolFee)),
|
|
462
|
+
evmExecutorFee: 0n,
|
|
463
|
+
tvmExecutorFee: 0n,
|
|
464
|
+
},
|
|
465
|
+
simulation: tacSimulationResult,
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
throw tacSimulationResult;
|
|
469
|
+
}
|
|
470
|
+
isRoundTrip = isRoundTrip ?? tacSimulationResult.outMessages != null;
|
|
471
|
+
let tonExecutorFeeInTON = 0n;
|
|
472
|
+
if (isRoundTrip) {
|
|
473
|
+
tonExecutorFeeInTON = BigInt(tacSimulationResult.suggestedTonExecutionFee);
|
|
474
|
+
}
|
|
475
|
+
const protocolFee = BigInt((0, ton_1.toNano)(fullStateCCL.tacProtocolFee)) +
|
|
476
|
+
BigInt(isRoundTrip) * BigInt((0, ton_1.toNano)(fullStateCCL.tonProtocolFee));
|
|
477
|
+
const feeParams = {
|
|
478
|
+
isRoundTrip: isRoundTrip,
|
|
479
|
+
gasLimit: tacSimulationResult.estimatedGas,
|
|
480
|
+
protocolFee: protocolFee,
|
|
481
|
+
evmExecutorFee: BigInt(tacSimulationResult.suggestedTacExecutionFee),
|
|
482
|
+
tvmExecutorFee: tonExecutorFeeInTON,
|
|
483
|
+
};
|
|
484
|
+
return { feeParams: feeParams, simulation: tacSimulationResult };
|
|
485
|
+
}
|
|
486
|
+
async getTransactionSimulationInfo(evmProxyMsg, sender, assets) {
|
|
487
|
+
const rawAssets = await this.convertAssetsToRawFormat(assets);
|
|
488
|
+
const aggregatedData = await this.aggregateTokens(rawAssets);
|
|
489
|
+
const transactionLinkerShardCount = aggregatedData.jettons.length == 0 ? 1 : aggregatedData.jettons.length;
|
|
490
|
+
const transactionLinker = (0, Utils_1.generateTransactionLinker)(sender.getSenderAddress(), transactionLinkerShardCount);
|
|
491
|
+
const evmValidExecutors = this.TACParams.trustedTACExecutors;
|
|
492
|
+
return await this.getFeeInfo(evmProxyMsg, transactionLinker, rawAssets, evmValidExecutors, false, undefined);
|
|
493
|
+
}
|
|
494
|
+
async prepareCrossChainTransaction(evmProxyMsg, caller, assets, options) {
|
|
495
|
+
let { forceSend = false, isRoundTrip = undefined, protocolFee = undefined, evmValidExecutors = [], evmExecutorFee = undefined, tvmValidExecutors = [], tvmExecutorFee = undefined, } = options || {};
|
|
496
|
+
const rawAssets = await this.convertAssetsToRawFormat(assets);
|
|
497
|
+
const aggregatedData = await this.aggregateTokens(rawAssets);
|
|
498
|
+
const tokensLength = aggregatedData.jettons.length + aggregatedData.nfts.length;
|
|
499
|
+
let transactionLinkerShardCount = tokensLength == 0 ? 1 : tokensLength;
|
|
500
|
+
const transactionLinker = (0, Utils_1.generateTransactionLinker)(caller, transactionLinkerShardCount);
|
|
501
|
+
if (evmValidExecutors.length == 0) {
|
|
502
|
+
evmValidExecutors = this.TACParams.trustedTACExecutors;
|
|
503
|
+
}
|
|
504
|
+
if (tvmValidExecutors.length == 0) {
|
|
505
|
+
tvmValidExecutors = this.TACParams.trustedTONExecutors;
|
|
506
|
+
}
|
|
507
|
+
const { feeParams } = await this.getFeeInfo(evmProxyMsg, transactionLinker, rawAssets, evmValidExecutors, forceSend, isRoundTrip);
|
|
508
|
+
if (evmProxyMsg.gasLimit == undefined) {
|
|
509
|
+
evmProxyMsg.gasLimit = feeParams.gasLimit;
|
|
510
|
+
}
|
|
511
|
+
if (evmExecutorFee != undefined) {
|
|
512
|
+
feeParams.evmExecutorFee = evmExecutorFee;
|
|
513
|
+
}
|
|
514
|
+
if (feeParams.isRoundTrip && tvmExecutorFee != undefined) {
|
|
515
|
+
feeParams.tvmExecutorFee = tvmExecutorFee;
|
|
516
|
+
}
|
|
517
|
+
if (protocolFee != undefined) {
|
|
518
|
+
feeParams.protocolFee = protocolFee;
|
|
519
|
+
}
|
|
520
|
+
const validExecutors = {
|
|
521
|
+
tac: evmValidExecutors,
|
|
522
|
+
ton: tvmValidExecutors,
|
|
523
|
+
};
|
|
524
|
+
const evmData = (0, Utils_1.buildEvmDataCell)(transactionLinker, evmProxyMsg, validExecutors);
|
|
525
|
+
const messages = await this.generateCrossChainMessages(caller, evmData, aggregatedData, feeParams);
|
|
526
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
527
|
+
const transaction = {
|
|
528
|
+
validUntil: +new Date() + 15 * 60 * 1000,
|
|
529
|
+
messages,
|
|
530
|
+
network: this.network,
|
|
531
|
+
};
|
|
532
|
+
return { transaction, transactionLinker };
|
|
533
|
+
}
|
|
534
|
+
async sendCrossChainTransaction(evmProxyMsg, sender, assets, options) {
|
|
535
|
+
const caller = sender.getSenderAddress();
|
|
536
|
+
const { transaction, transactionLinker } = await this.prepareCrossChainTransaction(evmProxyMsg, caller, assets, options);
|
|
537
|
+
console.log('*****Sending transaction: ', transaction);
|
|
538
|
+
const sendTransactionResult = await sender.sendShardTransaction(transaction, this.delay, this.network, this.TONParams.contractOpener);
|
|
539
|
+
return { sendTransactionResult, ...transactionLinker };
|
|
540
|
+
}
|
|
541
|
+
async sendCrossChainTransactions(sender, txs) {
|
|
542
|
+
const transactions = [];
|
|
543
|
+
const transactionLinkers = [];
|
|
544
|
+
const caller = sender.getSenderAddress();
|
|
545
|
+
for (const { options, assets, evmProxyMsg } of txs) {
|
|
546
|
+
const { transaction, transactionLinker } = await this.prepareCrossChainTransaction(evmProxyMsg, caller, assets, options);
|
|
547
|
+
transactions.push(transaction);
|
|
548
|
+
transactionLinkers.push(transactionLinker);
|
|
549
|
+
}
|
|
550
|
+
console.log('*****Sending transactions: ', transactions);
|
|
551
|
+
await sender.sendShardTransactions(transactions, this.delay, this.network, this.TONParams.contractOpener);
|
|
552
|
+
return transactionLinkers;
|
|
553
|
+
}
|
|
554
|
+
// TODO move to sdk.TAC, sdk.TON
|
|
555
|
+
async bridgeTokensToTON(signer, value, tonTarget, assets, tvmExecutorFee) {
|
|
556
|
+
if (assets == undefined) {
|
|
557
|
+
assets = [];
|
|
558
|
+
}
|
|
559
|
+
const crossChainLayerAddress = await this.TACParams.crossChainLayer.getAddress();
|
|
560
|
+
for (const asset of assets) {
|
|
561
|
+
if (asset.type == Struct_1.AssetType.FT) {
|
|
562
|
+
const tokenContract = this.artifacts.tac.wrappers.ERC20FactoryTAC.connect(asset.address, this.TACParams.provider);
|
|
563
|
+
const tx = await tokenContract.connect(signer).approve(crossChainLayerAddress, asset.rawAmount);
|
|
564
|
+
await tx.wait();
|
|
565
|
+
}
|
|
566
|
+
if (asset.type == Struct_1.AssetType.NFT) {
|
|
567
|
+
const tokenContract = this.artifacts.tac.wrappers.ERC721FactoryTAC.connect(asset.collectionAddress, this.TACParams.provider);
|
|
568
|
+
const tx = await tokenContract.connect(signer).approve(crossChainLayerAddress, asset.itemIndex);
|
|
569
|
+
await tx.wait();
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
const shardsKey = BigInt(Math.round(Math.random() * 1e18));
|
|
573
|
+
const protocolFee = await this.TACParams.crossChainLayer.getProtocolFee();
|
|
574
|
+
let tvmExecutorFeeInTON = 0n;
|
|
575
|
+
if (tvmExecutorFee != undefined) {
|
|
576
|
+
tvmExecutorFeeInTON = tvmExecutorFee;
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
tvmExecutorFeeInTON =
|
|
580
|
+
((((0, ton_1.toNano)('0.065') + (0, ton_1.toNano)('0.05')) * BigInt(assets.length + 1 + Number(value != 0n)) +
|
|
581
|
+
(0, ton_1.toNano)('0.2')) *
|
|
582
|
+
120n) /
|
|
583
|
+
100n; // TODO calc that
|
|
584
|
+
}
|
|
585
|
+
const tonToTacRate = 100n;
|
|
586
|
+
const scale = 10n ** 9n;
|
|
587
|
+
const tonToTacRateScaled = tonToTacRate * scale;
|
|
588
|
+
const tvmExecutorFeeInTAC = tonToTacRateScaled * tvmExecutorFeeInTON;
|
|
589
|
+
const outMessage = {
|
|
590
|
+
shardsKey: shardsKey,
|
|
591
|
+
tvmTarget: tonTarget,
|
|
592
|
+
tvmPayload: '',
|
|
593
|
+
tvmProtocolFee: protocolFee,
|
|
594
|
+
tvmExecutorFee: tvmExecutorFeeInTAC,
|
|
595
|
+
tvmValidExecutors: this.TACParams.trustedTONExecutors,
|
|
596
|
+
toBridge: assets
|
|
597
|
+
.filter((asset) => asset.type === Struct_1.AssetType.FT)
|
|
598
|
+
.map((asset) => ({
|
|
599
|
+
evmAddress: asset.address,
|
|
600
|
+
amount: asset.rawAmount,
|
|
601
|
+
})),
|
|
602
|
+
toBridgeNFT: assets
|
|
603
|
+
.filter((asset) => asset.type === Struct_1.AssetType.NFT)
|
|
604
|
+
.map((asset) => ({
|
|
605
|
+
evmAddress: asset.collectionAddress,
|
|
606
|
+
amount: 1n,
|
|
607
|
+
tokenId: asset.itemIndex,
|
|
608
|
+
})),
|
|
609
|
+
};
|
|
610
|
+
const encodedOutMessage = this.artifacts.tac.utils.encodeOutMessageV1(outMessage);
|
|
611
|
+
const outMsgVersion = 1n;
|
|
612
|
+
const totalValue = value + BigInt(outMessage.tvmProtocolFee) + BigInt(outMessage.tvmExecutorFee);
|
|
613
|
+
const tx = await this.TACParams.crossChainLayer
|
|
614
|
+
.connect(signer)
|
|
615
|
+
.sendMessage(outMsgVersion, encodedOutMessage, { value: totalValue });
|
|
616
|
+
await tx.wait();
|
|
617
|
+
return tx.hash;
|
|
618
|
+
}
|
|
619
|
+
get getTrustedTACExecutors() {
|
|
620
|
+
return this.TACParams.trustedTACExecutors;
|
|
621
|
+
}
|
|
622
|
+
get getTrustedTONExecutors() {
|
|
623
|
+
return this.TACParams.trustedTONExecutors;
|
|
624
|
+
}
|
|
625
|
+
async getEVMTokenAddress(tvmTokenAddress) {
|
|
626
|
+
if (tvmTokenAddress !== this.nativeTONAddress) {
|
|
627
|
+
(0, Utils_1.validateTVMAddress)(tvmTokenAddress);
|
|
628
|
+
tvmTokenAddress = ton_1.Address.parse(tvmTokenAddress).toString({ bounceable: true });
|
|
629
|
+
const { code: givenMinterCodeBOC } = await this.TONParams.contractOpener.getContractState((0, ton_1.address)(tvmTokenAddress));
|
|
630
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
631
|
+
if (givenMinterCodeBOC && this.TONParams.jettonMinterCode.equals(ton_1.Cell.fromBoc(givenMinterCodeBOC)[0])) {
|
|
632
|
+
const givenMinter = this.TONParams.contractOpener.open(new JettonMaster_1.JettonMaster((0, ton_1.address)(tvmTokenAddress)));
|
|
633
|
+
const evmAddress = await givenMinter.getEVMAddress();
|
|
634
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
635
|
+
return evmAddress;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return this.TACParams.tokenUtils.computeAddress(tvmTokenAddress);
|
|
639
|
+
}
|
|
640
|
+
async getTVMTokenAddress(evmTokenAddress) {
|
|
641
|
+
(0, Utils_1.validateEVMAddress)(evmTokenAddress);
|
|
642
|
+
const bytecode = await this.TACParams.provider.getCode(evmTokenAddress);
|
|
643
|
+
if (bytecode.includes(ethers_1.ethers.id('getInfo()').slice(2, 10))) {
|
|
644
|
+
const contract = new ethers_1.ethers.Contract(evmTokenAddress, this.TACParams.crossChainLayerTokenABI, this.TACParams.provider);
|
|
645
|
+
const info = await contract.getInfo.staticCall();
|
|
646
|
+
return info.tvmAddress;
|
|
647
|
+
}
|
|
648
|
+
const jettonMaster = JettonMaster_1.JettonMaster.createFromConfig({
|
|
649
|
+
evmTokenAddress,
|
|
650
|
+
crossChainLayerAddress: (0, ton_1.address)(this.TONParams.crossChainLayerAddress),
|
|
651
|
+
code: this.TONParams.jettonMinterCode,
|
|
652
|
+
walletCode: this.TONParams.jettonWalletCode,
|
|
653
|
+
});
|
|
654
|
+
return jettonMaster.address.toString();
|
|
655
|
+
}
|
|
656
|
+
async getTVMNFTAddress(evmNFTAddress, tokenId) {
|
|
657
|
+
(0, Utils_1.validateEVMAddress)(evmNFTAddress);
|
|
658
|
+
let nftCollection;
|
|
659
|
+
const bytecode = await this.TACParams.provider.getCode(evmNFTAddress);
|
|
660
|
+
if (bytecode.includes(ethers_1.ethers.id('getInfo()').slice(2, 10))) {
|
|
661
|
+
const contract = new ethers_1.ethers.Contract(evmNFTAddress, this.TACParams.crossChainLayerNFTABI, this.TACParams.provider);
|
|
662
|
+
const info = await contract.getInfo.staticCall();
|
|
663
|
+
nftCollection = this.TONParams.contractOpener.open(wrappers_1.NFTCollection.createFromAddress(info.tvmAddress));
|
|
664
|
+
}
|
|
665
|
+
else {
|
|
666
|
+
nftCollection = this.TONParams.contractOpener.open(wrappers_1.NFTCollection.createFromConfig({
|
|
667
|
+
ownerAddress: (0, ton_1.address)(this.TONParams.crossChainLayerAddress),
|
|
668
|
+
content: (0, ton_1.beginCell)().endCell(),
|
|
669
|
+
nftItemCode: this.TONParams.nftItemCode,
|
|
670
|
+
originalAddress: evmNFTAddress,
|
|
671
|
+
}, this.TONParams.nftCollectionCode));
|
|
672
|
+
}
|
|
673
|
+
return tokenId == undefined
|
|
674
|
+
? nftCollection.address.toString()
|
|
675
|
+
: (await nftCollection.getNFTAddressByIndex(tokenId)).toString();
|
|
676
|
+
}
|
|
677
|
+
async getEVMNFTAddress(tvmNFTAddress, addressType) {
|
|
678
|
+
(0, Utils_1.validateTVMAddress)(tvmNFTAddress);
|
|
679
|
+
tvmNFTAddress = ton_1.Address.parse(tvmNFTAddress).toString({ bounceable: true });
|
|
680
|
+
if (addressType == Struct_1.NFTAddressType.ITEM) {
|
|
681
|
+
tvmNFTAddress = (await this.getNFTItemData(tvmNFTAddress)).collectionAddress.toString();
|
|
682
|
+
addressType = Struct_1.NFTAddressType.COLLECTION;
|
|
683
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
684
|
+
}
|
|
685
|
+
const { code: givenNFTCollection } = await this.TONParams.contractOpener.getContractState((0, ton_1.address)(tvmNFTAddress));
|
|
686
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
687
|
+
if (givenNFTCollection && this.TONParams.nftCollectionCode.equals(ton_1.Cell.fromBoc(givenNFTCollection)[0])) {
|
|
688
|
+
const nftCollection = this.TONParams.contractOpener.open(wrappers_1.NFTCollection.createFromAddress((0, ton_1.address)(tvmNFTAddress)));
|
|
689
|
+
const evmAddress = await nftCollection.getOriginalAddress();
|
|
690
|
+
await (0, Utils_1.sleep)(this.delay * 1000);
|
|
691
|
+
return evmAddress.toString();
|
|
692
|
+
}
|
|
693
|
+
return this.TACParams.tokenUtils.computeAddress(tvmNFTAddress);
|
|
694
|
+
}
|
|
695
|
+
async isContractDeployedOnTVM(address) {
|
|
696
|
+
return (await this.TONParams.contractOpener.getContractState(ton_1.Address.parse(address))).state === 'active';
|
|
697
|
+
}
|
|
698
|
+
async simulateTACMessage(req) {
|
|
699
|
+
for (const endpoint of this.liteSequencerEndpoints) {
|
|
700
|
+
try {
|
|
701
|
+
const response = await axios_1.default.post(`${endpoint}/tac/simulator/simulate-message`, req, {
|
|
702
|
+
transformResponse: [Utils_1.toCamelCaseTransformer],
|
|
703
|
+
});
|
|
704
|
+
return response.data.response;
|
|
705
|
+
}
|
|
706
|
+
catch (error) {
|
|
707
|
+
console.error(`Error while simulating with ${endpoint}:`, error);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
throw errors_1.simulationError;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
exports.TacSdk = TacSdk;
|