我正在编写智能合约,以使用 FunC 语言为 TON 铸造可替代代币(jetton)。在编写测试用例时,我遇到以下错误:-
尝试在非活动合约上运行 get 方法
这是铸币厂合约:-
`#include "imports/stdlib.fc";
#include "imports/params.fc";
#include "imports/constants.fc";
#include "imports/jetton-utils.fc";
#include "imports/op-codes.fc";
#include "imports/utils.fc";
#include "imports/discovery-params.fc";
(int, slice, cell, cell) load_data() inline {
slice ds = get_data().begin_parse();
return (
ds~load_coins(),
ds~load_msg_addr(),
ds~load_ref(),
ds~load_ref()
);
}
() save_data(int total_supply, slice admin_address, cell content, cell jetton_wallet_code) impure inline {
set_data(begin_cell()
.store_coins(total_supply)
.store_slice(admin_address)
.store_ref(content)
.store_ref(jetton_wallet_code)
.end_cell()
);
}
() mint_tokens(slice to_address, cell jetton_wallet_code, int amount, cell master_msg) impure {
cell state_init = calculate_jetton_wallet_state_init(to_address, my_address(), jetton_wallet_code);
slice to_wallet_address = calculate_jetton_wallet_address(state_init);
var msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(to_wallet_address)
.store_coins(amount)
.store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)
.store_ref(state_init)
.store_ref(master_msg);
send_raw_message(msg.end_cell(), 1);
}
() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
if (in_msg_body.slice_empty?()) {
return ();
}
slice cs = in_msg_full.begin_parse();
int flags = cs~load_uint(4);
if (flags & 1) {
return ();
}
slice sender_address = cs~load_msg_addr();
cs~load_msg_addr();
cs~load_coins();
cs~skip_bits(1);
cs~load_coins();
int fwd_fee = cs~load_coins();
int op = in_msg_body~load_uint(32);
int query_id = in_msg_body~load_uint(64);
(int total_supply, slice admin_address, cell content, cell jetton_wallet_code) = load_data();
if (op == op::mint()) {
throw_unless(73, equal_slices(sender_address, admin_address));
slice to_address = in_msg_body~load_msg_addr();
int amount = in_msg_body~load_coins();
cell master_msg = in_msg_body~load_ref();
slice master_msg_cs = master_msg.begin_parse();
master_msg_cs~skip_bits(32 + 64);
int jetton_amount = master_msg_cs~load_coins();
mint_tokens(to_address, jetton_wallet_code, amount, master_msg);
save_data(total_supply + jetton_amount, admin_address, content, jetton_wallet_code);
return ();
}
if (op == op::burn_notification()) {
int jetton_amount = in_msg_body~load_coins();
slice from_address = in_msg_body~load_msg_addr();
throw_unless(74,
equal_slices(calculate_user_jetton_wallet_address(from_address, my_address(), jetton_wallet_code), sender_address)
);
save_data(total_supply - jetton_amount, admin_address, content, jetton_wallet_code);
slice response_address = in_msg_body~load_msg_addr();
if (response_address.preload_uint(2) != 0) {
var msg = begin_cell()
.store_uint(0x10, 6)
.store_slice(response_address)
.store_coins(0)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint(op::excesses(), 32)
.store_uint(query_id, 64);
send_raw_message(msg.end_cell(), 2 + 64);
}
return ();
}
if (op == op::provide_wallet_address()) {
throw_unless(75, msg_value > fwd_fee + const::provide_address_gas_consumption());
slice owner_address = in_msg_body~load_msg_addr();
int include_address? = in_msg_body~load_uint(1);
cell included_address = include_address?
? begin_cell().store_slice(owner_address).end_cell()
: null();
var msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(sender_address)
.store_coins(0)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint(op::take_wallet_address(), 32)
.store_uint(query_id, 64);
if (is_resolvable?(owner_address)) {
msg = msg.store_slice(calculate_user_jetton_wallet_address(owner_address, my_address(), jetton_wallet_code));
} else {
msg = msg.store_uint(0, 2);
}
send_raw_message(msg.store_maybe_ref(included_address).end_cell(), 64);
return ();
}
if (op == 3) {
throw_unless(73, equal_slices(sender_address, admin_address));
slice new_admin_address = in_msg_body~load_msg_addr();
save_data(total_supply, new_admin_address, content, jetton_wallet_code);
return ();
}
if (op == 4) {
throw_unless(73, equal_slices(sender_address, admin_address));
save_data(total_supply, admin_address, in_msg_body~load_ref(), jetton_wallet_code);
return ();
}
throw(0xffff);
}
(int, int, slice, cell, cell) get_jetton_data() method_id {
(int total_supply, slice admin_address, cell content, cell jetton_wallet_code) = load_data();
return (total_supply, -1, admin_address, content, jetton_wallet_code);
}
slice get_wallet_address(slice owner_address) method_id {
(int total_supply, slice admin_address, cell content, cell jetton_wallet_code) = load_data();
return calculate_user_jetton_wallet_address(owner_address, my_address(), jetton_wallet_code);
}`
这是钱包合约:-
#include "imports/stdlib.fc";
#include "imports/params.fc";
#include "imports/constants.fc";
#include "imports/jetton-utils.fc";
#include "imports/op-codes.fc";
#include "imports/utils.fc";
const min_tons_for_storage = 10000000;
const gas_consumption = 10000000;
(int, slice, slice, cell) load_data() inline {
slice ds = get_data().begin_parse();
return (ds~load_coins(), ds~load_msg_addr(), ds~load_msg_addr(), ds~load_ref());
}
() save_data (int balance, slice owner_address, slice jetton_master_address, cell jetton_wallet_code) impure inline {
set_data(pack_jetton_wallet_data(balance, owner_address, jetton_master_address, jetton_wallet_code));
}
() send_tokens (slice in_msg_body, slice sender_address, int msg_value, int fwd_fee) impure {
int query_id = in_msg_body~load_uint(64);
int jetton_amount = in_msg_body~load_coins();
slice to_owner_address = in_msg_body~load_msg_addr();
force_chain(to_owner_address);
(int balance, slice owner_address, slice jetton_master_address, cell jetton_wallet_code) = load_data();
balance -= jetton_amount;
throw_unless(705, equal_slices(owner_address, sender_address));
throw_unless(706, balance >= 0);
cell state_init = calculate_jetton_wallet_state_init(to_owner_address, jetton_master_address, jetton_wallet_code);
slice to_wallet_address = calculate_jetton_wallet_address(state_init);
slice response_address = in_msg_body~load_msg_addr();
cell custom_payload = in_msg_body~load_dict();
int forward_ton_amount = in_msg_body~load_coins();
throw_unless(708, slice_bits(in_msg_body) >= 1);
slice either_forward_payload = in_msg_body;
var msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(to_wallet_address)
.store_coins(0)
.store_uint(4 + 2 + 1, 1 + 4 + 4 + 64 + 32 + 1 + 1 + 1)
.store_ref(state_init);
var msg_body = begin_cell()
.store_uint(op::internal_transfer(), 32)
.store_uint(query_id, 64)
.store_coins(jetton_amount)
.store_slice(owner_address)
.store_slice(response_address)
.store_coins(forward_ton_amount)
.store_slice(either_forward_payload)
.end_cell();
msg = msg.store_ref(msg_body);
int fwd_count = forward_ton_amount ? 2 : 1;
throw_unless(709, msg_value >
forward_ton_amount +
fwd_count * fwd_fee +
(2 * gas_consumption + min_tons_for_storage));
send_raw_message(msg.end_cell(), 64);
save_data(balance, owner_address, jetton_master_address, jetton_wallet_code);
}
() receive_tokens (slice in_msg_body, slice sender_address, int my_ton_balance, int fwd_fee, int msg_value) impure {
(int balance, slice owner_address, slice jetton_master_address, cell jetton_wallet_code) = load_data();
int query_id = in_msg_body~load_uint(64);
int jetton_amount = in_msg_body~load_coins();
balance += jetton_amount;
slice from_address = in_msg_body~load_msg_addr();
slice response_address = in_msg_body~load_msg_addr();
throw_unless(707,
equal_slices(jetton_master_address, sender_address)
|
equal_slices(calculate_user_jetton_wallet_address(from_address, jetton_master_address, jetton_wallet_code), sender_address)
);
int forward_ton_amount = in_msg_body~load_coins();
int ton_balance_before_msg = my_ton_balance - msg_value;
int storage_fee = min_tons_for_storage - min(ton_balance_before_msg, min_tons_for_storage);
msg_value -= (storage_fee + gas_consumption);
if(forward_ton_amount) {
msg_value -= (forward_ton_amount + fwd_fee);
slice either_forward_payload = in_msg_body;
var msg_body = begin_cell()
.store_uint(op::transfer_notification(), 32)
.store_uint(query_id, 64)
.store_coins(jetton_amount)
.store_slice(from_address)
.store_slice(either_forward_payload)
.end_cell();
var msg = begin_cell()
.store_uint(0x10, 6)
.store_slice(owner_address)
.store_coins(forward_ton_amount)
.store_uint(1, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_ref(msg_body);
send_raw_message(msg.end_cell(), 1);
}
if ((response_address.preload_uint(2) != 0) & (msg_value > 0)) {
var msg = begin_cell()
.store_uint(0x10, 6)
.store_slice(response_address)
.store_coins(msg_value)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint(op::excesses(), 32)
.store_uint(query_id, 64);
send_raw_message(msg.end_cell(), 2);
}
save_data(balance, owner_address, jetton_master_address, jetton_wallet_code);
}
() burn_tokens (slice in_msg_body, slice sender_address, int msg_value, int fwd_fee) impure {
(int balance, slice owner_address, slice jetton_master_address, cell jetton_wallet_code) = load_data();
int query_id = in_msg_body~load_uint(64);
int jetton_amount = in_msg_body~load_coins();
slice response_address = in_msg_body~load_msg_addr();
balance -= jetton_amount;
throw_unless(705, equal_slices(owner_address, sender_address));
throw_unless(706, balance >= 0);
throw_unless(707, msg_value > fwd_fee + 2 * gas_consumption);
var msg_body = begin_cell()
.store_uint(op::burn_notification(), 32)
.store_uint(query_id, 64)
.store_coins(jetton_amount)
.store_slice(owner_address)
.store_slice(response_address)
.end_cell();
var msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(jetton_master_address)
.store_coins(0)
.store_uint(1, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_ref(msg_body);
send_raw_message(msg.end_cell(), 64);
save_data(balance, owner_address, jetton_master_address, jetton_wallet_code);
}
() on_bounce (slice in_msg_body) impure {
in_msg_body~skip_bits(32);
(int balance, slice owner_address, slice jetton_master_address, cell jetton_wallet_code) = load_data();
int op = in_msg_body~load_uint(32);
throw_unless(709, (op == op::internal_transfer()) | (op == op::burn_notification()));
int query_id = in_msg_body~load_uint(64);
int jetton_amount = in_msg_body~load_coins();
balance += jetton_amount;
save_data(balance, owner_address, jetton_master_address, jetton_wallet_code);
}
() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
if (in_msg_body.slice_empty?()) {
return ();
}
slice cs = in_msg_full.begin_parse();
int flags = cs~load_uint(4);
if (flags & 1) {
on_bounce(in_msg_body);
return ();
}
slice sender_address = cs~load_msg_addr();
cs~load_msg_addr();
cs~load_coins();
cs~skip_bits(1);
cs~load_coins();
int fwd_fee = muldiv(cs~load_coins(), 3, 2);
int op = in_msg_body~load_uint(32);
if (op == op::transfer()) {
send_tokens(in_msg_body, sender_address, msg_value, fwd_fee);
return ();
}
if (op == op::internal_transfer()) {
receive_tokens(in_msg_body, sender_address, my_balance, fwd_fee, msg_value);
return ();
}
if (op == op::burn()) {
burn_tokens(in_msg_body, sender_address, msg_value, fwd_fee);
return ();
}
throw(0xffff);
}
(int, slice, slice, cell) get_wallet_data() method_id {
return load_data();
}
这是 typescript 中测试用例的包装器:-
import {
Address,
beginCell,
Cell,
Contract,
contractAddress,
ContractProvider,
Sender,
SendMode,
toNano,
} from '@ton/core';
import { Op } from './JettonConstatnts';
export type JettonsConfig = { admin: Address; content: Cell; wallet_code: Cell };
export type JettonMinterContent = {
type: 0 | 1;
uri: string;
};
export function jettonMinterConfigToCell(config: JettonsConfig): Cell {
return beginCell()
.storeCoins(0)
.storeAddress(config.admin)
.storeRef(config.content)
.storeRef(config.wallet_code)
.endCell();
}
export function jettonsConfigToCell(config: JettonsConfig): Cell {
return beginCell().endCell();
}
export function jettonContentToCell(content: JettonMinterContent) {
return beginCell().storeUint(content.type, 8).storeStringTail(content.uri).endCell();
}
export class Jettons implements Contract {
constructor(
readonly address: Address,
readonly init?: { code: Cell; data: Cell },
) {}
static createFromAddress(address: Address) {
return new Jettons(address);
}
static createFromConfig(config: JettonsConfig, code: Cell, workchain = 0) {
const data = jettonsConfigToCell(config);
const init = { code, data };
return new Jettons(contractAddress(workchain, init), init);
}
async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {
await provider.internal(via, {
value,
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: beginCell().endCell(),
});
}
protected static jettonInternalTransfer(
jetton_amount: bigint,
forward_ton_amount: bigint,
response_addr?: Address,
query_id: number | bigint = 0,
) {
return beginCell()
.storeUint(Op.internal_transfer, 32)
.storeUint(query_id, 64)
.storeCoins(jetton_amount)
.storeAddress(null)
.storeAddress(response_addr)
.storeCoins(forward_ton_amount)
.storeBit(false)
.endCell();
}
static mintMessage(
from: Address,
to: Address,
jetton_amount: bigint,
forward_ton_amount: bigint,
total_ton_amount: bigint,
query_id: number | bigint = 0,
) {
const mintMsg = beginCell()
.storeUint(Op.internal_transfer, 32)
.storeUint(0, 64)
.storeCoins(jetton_amount)
.storeAddress(null)
.storeAddress(from)
.storeCoins(forward_ton_amount)
.storeMaybeRef(null)
.endCell();
return beginCell()
.storeUint(Op.mint, 32)
.storeUint(query_id, 64)
.storeAddress(to)
.storeCoins(total_ton_amount)
.storeCoins(jetton_amount)
.storeRef(mintMsg)
.endCell();
}
async sendMint(
provider: ContractProvider,
via: Sender,
to: Address,
jetton_amount: bigint,
forward_ton_amount: bigint,
total_ton_amount: bigint,
) {
if (total_ton_amount <= forward_ton_amount) {
throw new Error('Total ton amount should be > forward amount');
}
await provider.internal(via, {
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: Jettons.mintMessage(this.address, to, jetton_amount, forward_ton_amount, total_ton_amount),
value: total_ton_amount + toNano('0.015'),
});
}
static discoveryMessage(owner: Address, include_address: boolean) {
return beginCell().storeUint(0x2c76b973, 32).storeUint(0, 64)
.storeAddress(owner).storeBit(include_address)
.endCell();
}
async sendDiscovery(provider: ContractProvider, via: Sender, owner: Address, include_address: boolean, value:bigint = toNano('0.1')) {
await provider.internal(via, {
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: Jettons.discoveryMessage(owner, include_address),
value: value,
});
}
async getWalletAddress(provider: ContractProvider, owner: Address): Promise<Address> {
const res = await provider.get('get_wallet_address', [
{ type: 'slice', cell: beginCell().storeAddress(owner).endCell() },
]);
return res.stack.readAddress();
}
async getJettonData(provider: ContractProvider) {
let res = await provider.get('get_jetton_data', []);
let totalSupply = res.stack.readBigNumber();
let mintable = res.stack.readBoolean();
let adminAddress = res.stack.readAddress();
let content = res.stack.readCell();
let walletCode = res.stack.readCell();
return {
totalSupply,
mintable,
adminAddress,
content,
walletCode,
};
}
async getTotalSupply(provider: ContractProvider) {
let res = await this.getJettonData(provider);
return res.totalSupply;
}
}
2 钱包包装纸 :-
import { Address, beginCell, Cell, Contract, contractAddress, ContractProvider, Sender, SendMode, toNano } from '@ton/core';
export type JettonWalletConfig = {};
export function jettonWalletConfigToCell(config: JettonWalletConfig): Cell {
return beginCell().endCell();
}
export class JettonWallet implements Contract {
constructor(readonly address: Address, readonly init?: { code: Cell; data: Cell }) {}
static createFromAddress(address: Address) {
return new JettonWallet(address);
}
static createFromConfig(config: JettonWalletConfig, code: Cell, workchain = 0) {
const data = jettonWalletConfigToCell(config);
const init = { code, data };
return new JettonWallet(contractAddress(workchain, init), init);
}
async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) {
await provider.internal(via, {
value,
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: beginCell().endCell(),
});
}
async getJettonBalance(provider: ContractProvider) {
let state = await provider.getState();
if (state.state.type !== 'active') {
return 0n;
}
let res = await provider.get('get_wallet_data', []);
return res.stack.readBigNumber();
}
static transferMessage(jetton_amount: bigint, to: Address,
responseAddress:Address,
customPayload: Cell | null,
forward_ton_amount: bigint,
forwardPayload: Cell | null) {
return beginCell().storeUint(0xf8a7ea5, 32).storeUint(0, 64) // op, queryId
.storeCoins(jetton_amount).storeAddress(to)
.storeAddress(responseAddress)
.storeMaybeRef(customPayload)
.storeCoins(forward_ton_amount)
.storeMaybeRef(forwardPayload)
.endCell();
}
async sendTransfer(provider: ContractProvider, via: Sender,
value: bigint,
jetton_amount: bigint, to: Address,
responseAddress:Address,
customPayload: Cell,
forward_ton_amount: bigint,
forwardPayload: Cell) {
await provider.internal(via, {
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: JettonWallet.transferMessage(jetton_amount, to, responseAddress, customPayload, forward_ton_amount, forwardPayload),
value:value
});
}
/*
burn#595f07bc query_id:uint64 amount:(VarUInteger 16)
response_destination:MsgAddress custom_payload:(Maybe ^Cell)
= InternalMsgBody;
*/
static burnMessage(jetton_amount: bigint,
responseAddress:Address,
customPayload: Cell | null) {
return beginCell().storeUint(0x595f07bc, 32).storeUint(0, 64) // op, queryId
.storeCoins(jetton_amount).storeAddress(responseAddress)
.storeMaybeRef(customPayload)
.endCell();
}
async sendBurn(provider: ContractProvider, via: Sender, value: bigint,
jetton_amount: bigint,
responseAddress:Address,
customPayload: Cell) {
await provider.internal(via, {
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: JettonWallet.burnMessage(jetton_amount, responseAddress, customPayload),
value:value
});
}
/*
withdraw_tons#107c49ef query_id:uint64 = InternalMsgBody;
*/
static withdrawTonsMessage() {
return beginCell().storeUint(0x6d8e5e3c, 32).storeUint(0, 64) // op, queryId
.endCell();
}
async sendWithdrawTons(provider: ContractProvider, via: Sender) {
await provider.internal(via, {
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: JettonWallet.withdrawTonsMessage(),
value:toNano('0.1')
});
}
/*
withdraw_jettons#10 query_id:uint64 wallet:MsgAddressInt amount:Coins = InternalMsgBody;
*/
static withdrawJettonsMessage(from:Address, amount:bigint) {
return beginCell().storeUint(0x768a50b2, 32).storeUint(0, 64) // op, queryId
.storeAddress(from)
.storeCoins(amount)
.storeMaybeRef(null)
.endCell();
}
async sendWithdrawJettons(provider: ContractProvider, via: Sender, from:Address, amount:bigint) {
await provider.internal(via, {
sendMode: SendMode.PAY_GAS_SEPARATELY,
body: JettonWallet.withdrawJettonsMessage(from, amount),
value:toNano('0.1')
});
}
}
这是测试用例:-
import { Blockchain, BlockchainContractProvider, SandboxContract, TreasuryContract } from '@ton/sandbox';
import { Cell, toNano, ContractProvider, Address } from '@ton/core';
import { Jettons, jettonContentToCell } from '../wrappers/Jettons';
import '@ton/test-utils';
import { compile } from '@ton/blueprint';
import { JettonWallet } from '../wrappers/JettonWallet';
import { log } from 'console';
describe('Jettons', () => {
let code: Cell;
beforeAll(async () => {
code = await compile('Jettons');
});
let blockchain: Blockchain;
let deployer: SandboxContract<TreasuryContract>;
let notDeployer: SandboxContract<TreasuryContract>;
let jettons: SandboxContract<Jettons>;
let minter_code = new Cell();
let defaultContent: Cell;
let jwallet_code = new Cell();
let userWallet: any;
beforeEach(async () => {
jwallet_code = await compile('JettonWallet');
blockchain = await Blockchain.create();
minter_code = await compile('jettons');
notDeployer = await blockchain.treasury('notDeployer');
defaultContent = jettonContentToCell({ type: 1, uri: 'https://testjetton.org/content.json' });
deployer = await blockchain.treasury('deployer');
jettons = blockchain.openContract(
Jettons.createFromConfig(
{
admin: deployer.address,
content: defaultContent,
wallet_code: jwallet_code,
},
minter_code,
),
);
userWallet = async (address: Address) =>
blockchain.openContract(JettonWallet.createFromAddress(await jettons.getWalletAddress(address)));
});
it('should deploy', async () => {
const deployResult = await jettons.sendDeploy(deployer.getSender(), toNano('100'));
expect(deployResult.transactions).toHaveTransaction({
from: deployer.address,
to: jettons.address,
deploy: true,
});
});
it('should mint jettons', async () => {
let initialTotalSupply = await jettons.getTotalSupply();
console.log('initialTotalSupply', initialTotalSupply);
const deployerJettonWallet = await userWallet(deployer.address);
let initialJettonBalance = toNano('1000.23');
const mintResult = await jettons.sendMint(
deployer.getSender(),
deployer.address,
initialJettonBalance,
toNano('0.05'),
toNano('1'),
);
expect(mintResult.transactions).toHaveTransaction({
from: jettons.address,
to: deployerJettonWallet.address,
deploy: true,
});
expect(mintResult.transactions).toHaveTransaction({
from: deployerJettonWallet.address,
to: jettons.address,
});
expect(await deployerJettonWallet.getJettonBalance()).toEqual(initialJettonBalance);
expect(await jettons.getTotalSupply()).toEqual(initialTotalSupply + initialJettonBalance);
initialTotalSupply += initialJettonBalance;
let additionalJettonBalance = toNano('2.31');
await jettons.sendMint(
deployer.getSender(),
deployer.address,
additionalJettonBalance,
toNano('0.05'),
toNano('1'),
);
expect(await deployerJettonWallet.getJettonBalance()).toEqual(initialJettonBalance + additionalJettonBalance);
expect(await jettons.getTotalSupply()).toEqual(initialTotalSupply + additionalJettonBalance);
initialTotalSupply += additionalJettonBalance;
let otherJettonBalance = toNano('3.12');
await jettons.sendMint(
deployer.getSender(),
notDeployer.address,
otherJettonBalance,
toNano('0.05'),
toNano('1'),
);
const notDeployerJettonWallet = await userWallet(notDeployer.address);
expect(await notDeployerJettonWallet.getJettonBalance()).toEqual(otherJettonBalance);
expect(await jettons.getTotalSupply()).toEqual(initialTotalSupply + otherJettonBalance);
});
});
我尝试在测试用例中部署合约,但没有成功。我希望当我运行测试用例时,迷你过程应该起作用。
beforeEach(async () => {
jwallet_code = await compile('JettonWallet');
blockchain = await Blockchain.create();
minter_code = await compile('jettons');
notDeployer = await blockchain.treasury('notDeployer');
defaultContent = jettonContentToCell({ type: 1, uri: 'https://testjetton.org/content.json' });
deployer = await blockchain.treasury('deployer');
jettons = blockchain.openContract(
Jettons.createFromConfig(
{
admin: deployer.address,
content: defaultContent,
wallet_code: jwallet_code,
},
minter_code,
),
);
// Deploy and activate the Jettons contract
await jettons.sendDeploy(deployer.getSender(), toNano('1'));
await blockchain.waitForTransaction(jettons.address, { deploy: true });
userWallet = async (address: Address) =>
blockchain.openContract(JettonWallet.createFromAddress(await jettons.getWalletAddress(address)));
});
你必须部署合约并等待它被部署到区块链上,这里我使用了blockchain.waitForTransaction